mirror of https://github.com/vuejs/core.git
Merge branch 'main' into master
This commit is contained in:
commit
46e0d4ef33
66
.eslintrc.js
66
.eslintrc.js
|
@ -1,66 +0,0 @@
|
|||
const DOMGlobals = ['window', 'document']
|
||||
const NodeGlobals = ['module', 'require']
|
||||
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
sourceType: 'module'
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': [
|
||||
'error',
|
||||
// we are only using this rule to check for unused arguments since TS
|
||||
// catches unused variables but not args.
|
||||
{ varsIgnorePattern: '.*', args: 'none' }
|
||||
],
|
||||
// most of the codebase are expected to be env agnostic
|
||||
'no-restricted-globals': ['error', ...DOMGlobals, ...NodeGlobals],
|
||||
// since we target ES2015 for baseline support, we need to forbid object
|
||||
// rest spread usage (both assign and destructure)
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
'ObjectExpression > SpreadElement',
|
||||
'ObjectPattern > RestElement'
|
||||
]
|
||||
},
|
||||
overrides: [
|
||||
// tests, no restrictions (runs in Node / jest with jsdom)
|
||||
{
|
||||
files: ['**/__tests__/**', 'test-dts/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': 'off',
|
||||
'no-restricted-syntax': 'off'
|
||||
}
|
||||
},
|
||||
// shared, may be used in any env
|
||||
{
|
||||
files: ['packages/shared/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': 'off'
|
||||
}
|
||||
},
|
||||
// Packages targeting DOM
|
||||
{
|
||||
files: ['packages/{vue,vue-compat,runtime-dom}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals]
|
||||
}
|
||||
},
|
||||
// Packages targeting Node
|
||||
{
|
||||
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...DOMGlobals],
|
||||
'no-restricted-syntax': 'off'
|
||||
}
|
||||
},
|
||||
// Private package, browser only + no syntax restrictions
|
||||
{
|
||||
files: ['packages/template-explorer/**', 'packages/sfc-playground/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
'no-restricted-syntax': 'off'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
# update prettier & eslint config (#9162)
|
||||
bfe6b459d3a0ce6168611ee1ac7e6e789709df9d
|
|
@ -1,3 +1,2 @@
|
|||
open_collective: vuejs
|
||||
patreon: evanyou
|
||||
github: yyx990803
|
||||
open_collective: vuejs
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
name: "\U0001F41E Bug report"
|
||||
description: Create a report to help us improve
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Before You Start...**
|
||||
|
||||
This form is only for submitting bug reports. If you have a usage question
|
||||
or are unsure if this is really a bug, make sure to:
|
||||
|
||||
- Read the [docs](https://vuejs.org/)
|
||||
- Ask on [Discord Chat](https://chat.vuejs.org/)
|
||||
- Ask on [GitHub Discussions](https://github.com/vuejs/core/discussions)
|
||||
- Look for / ask questions on [Stack Overflow](https://stackoverflow.com/questions/ask?tags=vue.js)
|
||||
|
||||
Also try to search for your issue - it may have already been answered or even fixed in the development branch.
|
||||
However, if you find that an old, closed issue still persists in the latest version,
|
||||
you should open a new issue using the form below instead of commenting on the old issue.
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Vue version
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: reproduction-link
|
||||
attributes:
|
||||
label: Link to minimal reproduction
|
||||
description: |
|
||||
The easiest way to provide a reproduction is by showing the bug in [The SFC Playground](https://play.vuejs.org/).
|
||||
If it cannot be reproduced in the playground and requires a proper build setup, try [StackBlitz](https://vite.new/vue).
|
||||
If neither of these are suitable, you can always provide a GitHub repository.
|
||||
|
||||
The reproduction should be **minimal** - i.e. it should contain only the bare minimum amount of code needed
|
||||
to show the bug. See [Bug Reproduction Guidelines](https://github.com/vuejs/core/blob/main/.github/bug-repro-guidelines.md) for more details.
|
||||
|
||||
Please do not just fill in a random link. The issue will be closed if no valid reproduction is provided.
|
||||
placeholder: Reproduction Link
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps-to-reproduce
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: |
|
||||
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.
|
||||
placeholder: Steps to reproduce
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: What is expected?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actually-happening
|
||||
attributes:
|
||||
label: What is actually happening?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: system-info
|
||||
attributes:
|
||||
label: System Info
|
||||
description: Output of `npx envinfo --system --npmPackages vue --binaries --browsers`
|
||||
render: shell
|
||||
placeholder: System, Binaries, Browsers
|
||||
- type: textarea
|
||||
id: additional-comments
|
||||
attributes:
|
||||
label: Any additional comments?
|
||||
description: e.g. some background/context of how you ran into this bug.
|
|
@ -1,8 +1,14 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Create new issue
|
||||
url: https://new-issue.vuejs.org/?repo=vuejs/vue-next
|
||||
about: Please use the following link to create a new issue.
|
||||
- name: Feature Request
|
||||
url: https://github.com/vuejs/rfcs/discussions
|
||||
about: Suggest new features for consideration
|
||||
- name: Discord Chat
|
||||
url: https://chat.vuejs.org
|
||||
about: Ask questions and discuss with other Vue users in real time.
|
||||
- name: Questions & Discussions
|
||||
url: https://github.com/vuejs/core/discussions
|
||||
about: Use GitHub discussions for message-board style questions and discussions.
|
||||
- name: Patreon
|
||||
url: https://www.patreon.com/evanyou
|
||||
about: Love Vue.js? Please consider supporting us via Patreon.
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
## About Bug Reproductions
|
||||
|
||||
A bug reproduction is a piece of code that can run and demonstrate how a bug can happen.
|
||||
|
||||
### Text is not enough
|
||||
|
||||
It'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.
|
||||
|
||||
### A repro must be runnable
|
||||
|
||||
Screenshots 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.
|
||||
|
||||
### A repro should be minimal
|
||||
|
||||
Some 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:
|
||||
|
||||
You 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.
|
||||
|
||||
The problematic behavior may very well be caused by your code rather than by a bug in Vue.
|
||||
|
||||
A 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 aren't directly related to the problem.
|
||||
|
||||
### How to create a repro
|
||||
|
||||
For Vue 3 core reproductions, try reproducing it in [The SFC Playground](https://play.vuejs.org/).
|
||||
|
||||
If it cannot be reproduced in the playground and requires a proper build setup, try [StackBlitz](https://vite.new/vue).
|
||||
|
||||
If neither of these are suitable, you can always provide a GitHub repository.
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
Messages must be matched by the following regex:
|
||||
|
||||
``` js
|
||||
```regexp
|
||||
/^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip)(\(.+\))?: .{1,50}/
|
||||
```
|
||||
|
||||
|
@ -44,7 +44,7 @@ This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
|
|||
|
||||
### Full Message Format
|
||||
|
||||
A commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**:
|
||||
A commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
@ -74,9 +74,9 @@ The scope could be anything specifying the place of the commit change. For examp
|
|||
|
||||
The subject contains a succinct description of the change:
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize the first letter
|
||||
* no dot (.) at the end
|
||||
- use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
- don't capitalize the first letter
|
||||
- no dot (.) at the end
|
||||
|
||||
### Body
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Hi! 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:
|
||||
|
||||
- [Code of Conduct](https://github.com/vuejs/vue/blob/dev/.github/CODE_OF_CONDUCT.md)
|
||||
- [Code of Conduct](https://vuejs.org/about/coc.html)
|
||||
- [Issue Reporting Guidelines](#issue-reporting-guidelines)
|
||||
- [Pull Request Guidelines](#pull-request-guidelines)
|
||||
- [Development Setup](#development-setup)
|
||||
|
@ -17,7 +17,33 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
|
|||
|
||||
## Pull Request Guidelines
|
||||
|
||||
- Checkout a topic branch from a base branch, e.g. `master`, and merge back against that branch.
|
||||
### What kinds of Pull Requests are accepted?
|
||||
|
||||
- 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.
|
||||
|
||||
- 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.
|
||||
|
||||
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 spreads across the codebase, it is likely not worth it, or the approach should be reconsidered.
|
||||
|
||||
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.
|
||||
|
||||
- Chore: typos, comment improvements, build config, CI config, etc. For typos and comment changes, try to combine multiple of them into a single PR.
|
||||
|
||||
- **It should be noted that we discourage contributors from submitting code refactors that are largely stylistic.** Code refactors are only accepted if it improves performance, or comes with sufficient explanations on why it objectively improves the code quality (e.g. makes a related feature implementation easier).
|
||||
|
||||
The reason is that code readability is subjective. The maintainers of this project have chosen to write the code in its current style based on our preferences, and we do not want to spend time explaining our stylistic preferences. Contributors should just respect the established conventions when contributing code.
|
||||
|
||||
Another aspect of it is that large scale stylistic changes result in massive diffs that touch multiple files, adding noise to the git history and makes tracing behavior changes across commits more cumbersome.
|
||||
|
||||
### Pull Request Checklist
|
||||
|
||||
- Vue core has two primary work branches: `main` and `minor`.
|
||||
|
||||
- If your pull request is a feature that adds new API surface, it should be submitted against the `minor` branch.
|
||||
|
||||
- Otherwise, it should be submitted against the `main` branch.
|
||||
|
||||
- [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.
|
||||
|
||||
- If adding a new feature:
|
||||
|
||||
|
@ -28,36 +54,77 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
|
|||
|
||||
- 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)`.
|
||||
- Provide a detailed description of the bug in the PR. Live demo preferred.
|
||||
- Add appropriate test coverage if applicable. You can check the coverage of your code addition by running `yarn test --coverage`.
|
||||
- Add appropriate test coverage if applicable. You can check the coverage of your code addition by running `nr test-coverage`.
|
||||
|
||||
- It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging.
|
||||
|
||||
- Make sure tests pass!
|
||||
|
||||
- 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 [yorkie](https://github.com/yyx990803/yorkie)).
|
||||
- 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)).
|
||||
|
||||
- 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 [yorkie](https://github.com/yyx990803/yorkie)).
|
||||
- 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)).
|
||||
|
||||
### Advanced Pull Request Tips
|
||||
|
||||
- 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.
|
||||
|
||||
- Consider the performance / size impact of the changes, and whether the bug being fixes 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.
|
||||
|
||||
- Is the code perf-sensitive (e.g. in "hot paths" like component updates or the vdom patch function?)
|
||||
|
||||
- If the branch is dev-only, performance is less of a concern.
|
||||
|
||||
- Check how much extra bundle size the change introduces.
|
||||
- Make sure to put dev-only code in `__DEV__` branches so they are tree-shakable.
|
||||
- Runtime code is more sensitive to size increase than compiler code.
|
||||
- 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`.
|
||||
|
||||
## Development Setup
|
||||
|
||||
You will need [Node.js](http://nodejs.org) **version 10+**, and [Yarn 1.x](https://yarnpkg.com/en/docs/install).
|
||||
You 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).
|
||||
|
||||
We 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 running npm scripts easier.
|
||||
|
||||
After cloning the repo, run:
|
||||
|
||||
```bash
|
||||
$ yarn # install the dependencies of the project
|
||||
$ pnpm i # install the dependencies of the project
|
||||
```
|
||||
|
||||
A high level overview of tools used:
|
||||
|
||||
- [TypeScript](https://www.typescriptlang.org/) as the development language
|
||||
- [Rollup](https://rollupjs.org) for bundling
|
||||
- [Jest](https://jestjs.io/) for unit testing
|
||||
- [Vite](https://vitejs.dev/) and [ESBuild](https://esbuild.github.io/) for development bundling
|
||||
- [Rollup](https://rollupjs.org) for production bundling
|
||||
- [Vitest](https://vitest.dev/) for unit testing
|
||||
- [Prettier](https://prettier.io/) for code formatting
|
||||
- [ESLint](https://eslint.org/) for static error prevention (outside of types)
|
||||
|
||||
## Git Hooks
|
||||
|
||||
The project uses [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks) to enforce the following on each commit:
|
||||
|
||||
- Type check the entire project
|
||||
- Automatically format changed files using Prettier
|
||||
- Verify commit message format (logic in `scripts/verify-commit.js`)
|
||||
|
||||
## Scripts
|
||||
|
||||
### `yarn build`
|
||||
**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`.
|
||||
|
||||
The `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".
|
||||
|
||||
- [`nr build`](#nr-build)
|
||||
- [`nr build-dts`](#nr-build-dts)
|
||||
- [`nr check`](#nr-check)
|
||||
- [`nr dev`](#nr-dev)
|
||||
- [`nr dev-sfc`](#nr-dev-sfc)
|
||||
- [`nr dev-esm`](#nr-dev-esm)
|
||||
- [`nr dev-compiler`](#nr-dev-compiler)
|
||||
- [`nr test`](#nr-test)
|
||||
- [`nr test-dts`](#nr-test-dts)
|
||||
|
||||
### `nr build`
|
||||
|
||||
The `build` script builds all public packages (packages without `private: true` in their `package.json`).
|
||||
|
||||
|
@ -65,12 +132,14 @@ Packages to build can be specified with fuzzy matching:
|
|||
|
||||
```bash
|
||||
# build runtime-core only
|
||||
yarn build runtime-core
|
||||
nr build runtime-core
|
||||
|
||||
# build all packages matching "runtime"
|
||||
yarn build runtime --all
|
||||
nr build runtime --all
|
||||
```
|
||||
|
||||
Note 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.
|
||||
|
||||
#### Build Formats
|
||||
|
||||
By 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:
|
||||
|
@ -86,74 +155,89 @@ Additional formats that only apply to the main `vue` package:
|
|||
- **`esm-bundler-runtime`**
|
||||
- **`esm-browser-runtime`**
|
||||
|
||||
More details about each of these formats can be found in the [`vue` package README](https://github.com/vuejs/vue-next/blob/master/packages/vue/README.md#which-dist-file-to-use) and the [Rollup config file](https://github.com/vuejs/vue-next/blob/master/rollup.config.js).
|
||||
More 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).
|
||||
|
||||
For example, to build `runtime-core` with the global build only:
|
||||
|
||||
```bash
|
||||
yarn build runtime-core -f global
|
||||
nr build runtime-core -f global
|
||||
```
|
||||
|
||||
Multiple formats can be specified as a comma-separated list:
|
||||
|
||||
```bash
|
||||
yarn build runtime-core -f esm-browser,cjs
|
||||
nr build runtime-core -f esm-browser,cjs
|
||||
```
|
||||
|
||||
#### Build with Source Maps
|
||||
|
||||
Use the `--sourcemap` or `-s` flag to build with source maps. Note this will make the build much slower.
|
||||
|
||||
#### Build with Type Declarations
|
||||
### `nr build-dts`
|
||||
|
||||
The `--types` or `-t` flag will generate type declarations during the build and in addition:
|
||||
This 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.
|
||||
|
||||
- Roll the declarations into a single `.d.ts` file for each package;
|
||||
- Generate an API report in `<projectRoot>/temp/<packageName>.api.md`. This report contains potential warnings emitted by [api-extractor](https://api-extractor.com/).
|
||||
- Generate an API model json in `<projectRoot>/temp/<packageName>.api.json`. This file can be used to generate a Markdown version of the exported APIs.
|
||||
### `nr check`
|
||||
|
||||
### `yarn dev`
|
||||
### `nr dev`
|
||||
|
||||
The `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:
|
||||
|
||||
```bash
|
||||
$ yarn dev
|
||||
$ nr dev
|
||||
|
||||
> rollup v1.19.4
|
||||
> bundles packages/vue/src/index.ts → packages/vue/dist/vue.global.js...
|
||||
> built: packages/vue/dist/vue.global.js
|
||||
```
|
||||
|
||||
- The `dev` script also supports fuzzy match for the target package, but will only match the first package matched.
|
||||
- **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.
|
||||
|
||||
- The `dev` script does not support fuzzy match - you must specify the full package name, e.g. `nr dev runtime-core`.
|
||||
|
||||
- The `dev` script supports specifying build format via the `-f` flag just like the `build` script.
|
||||
|
||||
- The `dev` script also supports the `-s` flag for generating source maps, but it will make rebuilds slower.
|
||||
|
||||
### `yarn dev-compiler`
|
||||
- The `dev` script supports the `-i` flag for inlining all deps. This is useful when debugging `esm-bundler` builds which externalizes deps by default.
|
||||
|
||||
The `dev-compiler` script builds, watches and serves the [Template Explorer](https://github.com/vuejs/vue-next/tree/master/packages/template-explorer) at `http://localhost:5000`. This is extremely useful when working on the compiler.
|
||||
### `nr dev-sfc`
|
||||
|
||||
### `yarn test`
|
||||
Shortcut 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.
|
||||
|
||||
The `test` script simply calls the `jest` binary, so all [Jest CLI Options](https://jestjs.io/docs/en/cli) can be used. Some examples:
|
||||
### `nr dev-esm`
|
||||
|
||||
Builds 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.
|
||||
|
||||
### `nr dev-compiler`
|
||||
|
||||
The `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.
|
||||
|
||||
### `nr test`
|
||||
|
||||
The `test` script simply calls the `vitest` binary, so all [Vitest CLI Options](https://vitest.dev/guide/cli.html#options) can be used. Some examples:
|
||||
|
||||
```bash
|
||||
# run all tests
|
||||
$ yarn test
|
||||
# run all tests in watch mode
|
||||
$ nr test
|
||||
|
||||
# run tests in watch mode
|
||||
$ yarn test --watch
|
||||
# run once and exit (equivalent to `vitest run`)
|
||||
$ nr test run
|
||||
|
||||
# run all tests under the runtime-core package
|
||||
$ yarn test runtime-core
|
||||
$ nr test runtime-core
|
||||
|
||||
# run tests in a specific file
|
||||
$ yarn test fileName
|
||||
# run tests in files matching the pattern
|
||||
$ nr test <fileNamePattern>
|
||||
|
||||
# run a specific test in a specific file
|
||||
$ yarn test fileName -t 'test name'
|
||||
# run a specific test in specific files
|
||||
$ nr test <fileNamePattern> -t 'test name'
|
||||
```
|
||||
|
||||
Tests 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`.
|
||||
|
||||
### `nr test-dts`
|
||||
|
||||
Runs `nr build-dts` first, then verify the type tests in `packages-private/dts-test` are working correctly against the actual built type declarations.
|
||||
|
||||
## Project Structure
|
||||
|
||||
This repository employs a [monorepo](https://en.wikipedia.org/wiki/Monorepo) setup which hosts a number of associated packages under the `packages` directory:
|
||||
|
@ -172,16 +256,22 @@ This repository employs a [monorepo](https://en.wikipedia.org/wiki/Monorepo) set
|
|||
|
||||
- `compiler-dom`: Compiler with additional plugins specifically targeting the browser.
|
||||
|
||||
- `compiler-sfc`: Lower level utilities for compiling Vue Single File Components.
|
||||
|
||||
- `compiler-ssr`: Compiler that produces render functions optimized for server-side rendering.
|
||||
|
||||
- `template-explorer`: A development tool for debugging compiler output. You can run `yarn dev template-explorer` and open its `index.html` to get a repl of template compilation based on current source code.
|
||||
|
||||
A [live version](https://vue-next-template-explorer.netlify.com) of the template explorer is also available, which can be used for providing reproductions for compiler bugs. You can also pick the deployment for a specific commit from the [deploy logs](https://app.netlify.com/sites/vue-next-template-explorer/deploys).
|
||||
|
||||
- `shared`: Internal utilities shared across multiple packages (especially environment-agnostic utils used by both runtime and compiler packages).
|
||||
|
||||
- `vue`: The public facing "full build" which includes both the runtime AND the compiler.
|
||||
|
||||
- Private utility packages:
|
||||
|
||||
- `dts-test`: Contains type-only tests against generated dts files.
|
||||
|
||||
- `sfc-playground`: The playground continuously deployed at https://play.vuejs.org. To run the playground locally, use [`nr dev-sfc`](#nr-dev-sfc).
|
||||
|
||||
- `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).
|
||||
|
||||
### Importing Packages
|
||||
|
||||
The 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:
|
||||
|
@ -192,33 +282,35 @@ import { h } from '@vue/runtime-core'
|
|||
|
||||
This is made possible via several configurations:
|
||||
|
||||
- For TypeScript, `compilerOptions.path` in `tsconfig.json`
|
||||
- For Jest, `moduleNameMapper` in `jest.config.js`
|
||||
- For plain Node.js, they are linked using [Yarn Workspaces](https://yarnpkg.com/blog/2017/08/02/introducing-workspaces/).
|
||||
- For TypeScript, `compilerOptions.paths` in `tsconfig.json`
|
||||
- Vitest and Rollup share the same set of aliases from `scripts/aliases.js`
|
||||
- For plain Node.js, they are linked using [PNPM Workspaces](https://pnpm.io/workspaces).
|
||||
|
||||
### Package Dependencies
|
||||
|
||||
```
|
||||
+---------------------+
|
||||
| |
|
||||
| @vue/compiler-sfc |
|
||||
| |
|
||||
+-----+--------+------+
|
||||
| |
|
||||
v v
|
||||
+---------------------+ +----------------------+
|
||||
| | | |
|
||||
+------------>| @vue/compiler-dom +--->| @vue/compiler-core |
|
||||
| | | | |
|
||||
+----+----+ +---------------------+ +----------------------+
|
||||
| |
|
||||
| vue |
|
||||
| |
|
||||
+----+----+ +---------------------+ +----------------------+ +-------------------+
|
||||
| | | | | | |
|
||||
+------------>| @vue/runtime-dom +--->| @vue/runtime-core +--->| @vue/reactivity |
|
||||
| | | | | |
|
||||
+---------------------+ +----------------------+ +-------------------+
|
||||
```mermaid
|
||||
flowchart LR
|
||||
compiler-sfc["@vue/compiler-sfc"]
|
||||
compiler-dom["@vue/compiler-dom"]
|
||||
compiler-core["@vue/compiler-core"]
|
||||
vue["vue"]
|
||||
runtime-dom["@vue/runtime-dom"]
|
||||
runtime-core["@vue/runtime-core"]
|
||||
reactivity["@vue/reactivity"]
|
||||
|
||||
subgraph "Runtime Packages"
|
||||
runtime-dom --> runtime-core
|
||||
runtime-core --> reactivity
|
||||
end
|
||||
|
||||
subgraph "Compiler Packages"
|
||||
compiler-sfc --> compiler-core
|
||||
compiler-sfc --> compiler-dom
|
||||
compiler-dom --> compiler-core
|
||||
end
|
||||
|
||||
vue ---> compiler-dom
|
||||
vue --> runtime-dom
|
||||
```
|
||||
|
||||
There are some rules to follow when importing across package boundaries:
|
||||
|
@ -231,7 +323,7 @@ There are some rules to follow when importing across package boundaries:
|
|||
|
||||
## Contributing Tests
|
||||
|
||||
Unit tests are collocated with the code being tested in each package, inside directories named `__tests__`. Consult the [Jest docs](https://jestjs.io/docs/en/using-matchers) and existing test cases for how to write new test specs. Here are some additional guidelines:
|
||||
Unit 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:
|
||||
|
||||
- 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.
|
||||
|
||||
|
@ -239,13 +331,11 @@ Unit tests are collocated with the code being tested in each package, inside dir
|
|||
|
||||
- Only use platform-specific runtimes if the test is asserting platform-specific behavior.
|
||||
|
||||
Test coverage is continuously deployed at https://vue-next-coverage.netlify.app/. 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 meaning use case.
|
||||
Test 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 meaning use case.
|
||||
|
||||
### Testing Type Definition Correctness
|
||||
|
||||
This project uses [tsd](https://github.com/SamVerschueren/tsd) to test the built definition files (`*.d.ts`).
|
||||
|
||||
Type tests are located in the `test-dts` directory. To run the dts tests, run `yarn 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 simply running `yarn test-dts`.
|
||||
Type 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`.
|
||||
|
||||
## Financial Contribution
|
||||
|
||||
|
@ -262,4 +352,4 @@ Funds donated via Patreon go directly to support Evan You's full-time work on Vu
|
|||
|
||||
Thank you to all the people who have already contributed to Vue.js!
|
||||
|
||||
<a href="https://github.com/vuejs/vue/graphs/contributors"><img src="https://opencollective.com/vuejs/contributors.svg?width=890" /></a>
|
||||
<a href="https://github.com/vuejs/core/graphs/contributors"><img src="https://opencollective.com/vuejs/contributors.svg?width=890" /></a>
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: monthly
|
||||
open-pull-requests-limit: 10
|
||||
versioning-strategy: lockfile-only
|
||||
ignore:
|
||||
- dependency-name: "@types/node"
|
||||
versions:
|
||||
- 14.14.24
|
||||
- 14.14.37
|
||||
- dependency-name: "@babel/parser"
|
||||
versions:
|
||||
- 7.12.11
|
||||
- 7.12.13
|
||||
- 7.12.14
|
||||
- 7.12.15
|
||||
- 7.12.16
|
||||
- 7.12.17
|
||||
- 7.13.0
|
||||
- 7.13.10
|
||||
- 7.13.11
|
||||
- 7.13.13
|
||||
- 7.13.4
|
||||
- 7.13.9
|
||||
- dependency-name: eslint
|
||||
versions:
|
||||
- 7.23.0
|
||||
- dependency-name: postcss
|
||||
versions:
|
||||
- 8.2.4
|
||||
- 8.2.5
|
||||
- 8.2.7
|
||||
- 8.2.8
|
||||
- dependency-name: typescript
|
||||
versions:
|
||||
- 4.2.2
|
||||
- dependency-name: "@babel/types"
|
||||
versions:
|
||||
- 7.12.12
|
||||
- 7.12.13
|
||||
- 7.12.17
|
||||
- 7.13.0
|
||||
- dependency-name: pug-code-gen
|
||||
versions:
|
||||
- 2.0.3
|
||||
- dependency-name: estree-walker
|
||||
versions:
|
||||
- 2.0.2
|
||||
- dependency-name: "@typescript-eslint/parser"
|
||||
versions:
|
||||
- 4.14.2
|
||||
- 4.15.0
|
||||
- dependency-name: "@microsoft/api-extractor"
|
||||
versions:
|
||||
- 7.13.1
|
||||
- dependency-name: rollup
|
||||
versions:
|
||||
- 2.38.5
|
||||
- dependency-name: node-notifier
|
||||
versions:
|
||||
- 8.0.1
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 200 KiB |
Binary file not shown.
After Width: | Height: | Size: 262 KiB |
|
@ -0,0 +1,123 @@
|
|||
# Vue Core Maintenance Handbook
|
||||
|
||||
Unlike [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!
|
||||
|
||||
- [Issue Triage Workflow](#issue-triage-workflow)
|
||||
- [Pull Request Review Guidelines](#pull-request-review-guidelines)
|
||||
- [Reviewing a Fix](#reviewing-a-fix)
|
||||
- [Reviewing a Refactor](#reviewing-a-refactor)
|
||||
- [Reviewing a Feature](#reviewing-a-feature)
|
||||
- [Common Considerations for All PRs](#common-considerations-for-all-prs)
|
||||
- [PR Merge Rules for Team Members](#pr-merge-rules-for-team-members)
|
||||
- [Git Branch and Release Workflow](#git-branch-and-release-workflow)
|
||||
|
||||
## Issue Triage Workflow
|
||||
|
||||

|
||||
|
||||
## Pull Request Review Guidelines
|
||||
|
||||
The first step of reviewing a PR is to identify its purpose. We can usually put a PR in one of these categories:
|
||||
|
||||
- **Fix**: fixes some wrong behavior. Usually associated with an issue that has a reproduction of the behavior being fixed.
|
||||
- **Refactor**: improves performance or code quality, but does not affect behavior.
|
||||
- **Feature**: implements something that increases the public API surface.
|
||||
|
||||
Depending on the type of the PR, different considerations need to be taken into account.
|
||||
|
||||
### Reviewing a Fix
|
||||
|
||||
- Is the PR fixing a well defined issue / bug report?
|
||||
- If not, ask to clarify context / provide reproduction or failing test case
|
||||
- In most cases, a fix PR should include a test case that fails without the fix.
|
||||
- Is it the right fix?
|
||||
- If not, guide user to rework the PR.
|
||||
- If the needed change is small and obvious, can directly push to the PR or add inline suggestions to reduce the back-and-forth.
|
||||
- Is the cost justified?
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
#### Verifying a Fix
|
||||
|
||||
- **Always locally verify that the fix indeed fixes the original behavior, either through a reproduction or a failing test case.**
|
||||
- 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).
|
||||
- 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.
|
||||
|
||||
### Reviewing a Refactor
|
||||
|
||||
- Performance: if a refactor PR claims to improve performance, there should be benchmarks showcasing said performance unless the improvement is self-explanatory.
|
||||
|
||||
- Code quality / stylistic PRs: we should be conservative on merging this type 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.
|
||||
|
||||
- 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.
|
||||
|
||||
### Reviewing a Feature
|
||||
|
||||
- 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.
|
||||
|
||||
- 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:
|
||||
|
||||
- Adding a new built-in component or directive is "significant" and definitely requires an RFC.
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
- 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.
|
||||
|
||||
### Common Considerations for All PRs
|
||||
|
||||
- Scope: a PR should only contain changes directly related to the problem being addressed. It should not contain unnecessary code style changes.
|
||||
|
||||
- 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.
|
||||
|
||||
- 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.
|
||||
|
||||
- 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.
|
||||
|
||||
- Make sure to put dev-only code in `__DEV__` branches so they are tree-shakable.
|
||||
|
||||
- Runtime code is more sensitive to size increase than compiler code.
|
||||
|
||||
- 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`.
|
||||
|
||||
- Performance
|
||||
|
||||
- Be careful about code changes in "hot paths", in particular the Virtual DOM renderer (`runtime-core/src/renderer.ts`) and component instantiation code.
|
||||
|
||||
- Potential Breakage
|
||||
- avoiding runtime behavior breakage is the highest priority
|
||||
- if not sure, use `ecosystem-ci` to verify!
|
||||
- some fix inevitably cause behavior change, these must be discussed case-by-case
|
||||
- type level breakage (e.g upgrading TS) is possible between minors
|
||||
|
||||
## PR Merge Rules for Team Members
|
||||
|
||||
Given that the PR meets the review requirements:
|
||||
|
||||
- Chore / dependencies bumps: can merge directly.
|
||||
- Fixes / refactors: can merge with two or more approvals from team members.
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
## Git Branch and Release Workflow
|
||||
|
||||
We use two primary work branches: `main` and `minor`.
|
||||
|
||||
- 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.
|
||||
|
||||
- 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.
|
||||
|
||||
Before each release, we merge latest `main` into `minor` so it would include the latest bug fixes.
|
||||
|
||||
When 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.
|
||||
|
||||

|
||||
|
||||
### Reasoning Behind the Workflow
|
||||
|
||||
The 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.
|
||||
|
||||
Vue 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.
|
||||
|
||||
But 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.
|
||||
|
||||
This 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.
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
$schema: 'https://docs.renovatebot.com/renovate-schema.json',
|
||||
extends: ['config:base', 'schedule:weekly', 'group:allNonMajor'],
|
||||
labels: ['dependencies'],
|
||||
ignorePaths: ['**/__tests__/**'],
|
||||
rangeStrategy: 'bump',
|
||||
packageRules: [
|
||||
{
|
||||
depTypeList: ['peerDependencies'],
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
groupName: 'test',
|
||||
matchPackageNames: ['vitest', 'jsdom', 'puppeteer'],
|
||||
matchPackagePrefixes: ['@vitest'],
|
||||
},
|
||||
{
|
||||
groupName: 'playground',
|
||||
matchFileNames: [
|
||||
'packages-private/sfc-playground/package.json',
|
||||
'packages-private/template-explorer/package.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
groupName: 'compiler',
|
||||
matchPackageNames: ['magic-string'],
|
||||
matchPackagePrefixes: ['@babel', 'postcss'],
|
||||
},
|
||||
{
|
||||
groupName: 'build',
|
||||
matchPackageNames: ['vite', '@swc/core'],
|
||||
matchPackagePrefixes: ['rollup', 'esbuild', '@rollup', '@vitejs'],
|
||||
},
|
||||
{
|
||||
groupName: 'lint',
|
||||
matchPackageNames: ['simple-git-hooks', 'lint-staged'],
|
||||
matchPackagePrefixes: ['typescript-eslint', 'eslint', 'prettier'],
|
||||
},
|
||||
],
|
||||
ignoreDeps: [
|
||||
'vue',
|
||||
|
||||
// manually bumping
|
||||
'node',
|
||||
'typescript',
|
||||
|
||||
// ESM only
|
||||
'estree-walker',
|
||||
|
||||
// pinned
|
||||
// https://github.com/vuejs/core/issues/10300#issuecomment-1940855364
|
||||
'lru-cache',
|
||||
|
||||
// pinned
|
||||
// https://github.com/vuejs/core/commit/a012e39b373f1b6918e5c89856e8f902e1bfa14d
|
||||
'@rollup/plugin-replace',
|
||||
|
||||
// pinned
|
||||
// only used in example for e2e tests
|
||||
'marked',
|
||||
|
||||
// pinned, 5.0+ has exports issues
|
||||
// https://github.com/vuejs/core/issues/11603
|
||||
'entities',
|
||||
],
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
name: autofix.ci
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
autofix:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
|
||||
- run: pnpm install
|
||||
|
||||
- name: Run eslint
|
||||
run: pnpm run lint --fix
|
||||
|
||||
- name: Run prettier
|
||||
run: pnpm run format
|
||||
|
||||
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
|
|
@ -0,0 +1,33 @@
|
|||
name: canary minor release
|
||||
on:
|
||||
# Runs every Monday at 1 AM UTC (9:00 AM in Singapore)
|
||||
schedule:
|
||||
- cron: 0 1 * * MON
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
canary:
|
||||
# prevents this action from running on forks
|
||||
if: github.repository == 'vuejs/core'
|
||||
runs-on: ubuntu-latest
|
||||
environment: Release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: minor
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
|
||||
- run: pnpm install
|
||||
|
||||
- run: pnpm release --canary --publish --tag minor
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@ -0,0 +1,31 @@
|
|||
name: canary release
|
||||
on:
|
||||
# Runs every Monday at 1 AM UTC (9:00 AM in Singapore)
|
||||
schedule:
|
||||
- cron: 0 1 * * MON
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
canary:
|
||||
# prevents this action from running on forks
|
||||
if: github.repository == 'vuejs/core'
|
||||
runs-on: ubuntu-latest
|
||||
environment: Release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
|
||||
- run: pnpm install
|
||||
|
||||
- run: pnpm release --canary --publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@ -3,37 +3,40 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- '**'
|
||||
tags:
|
||||
- '!**'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- minor
|
||||
|
||||
jobs:
|
||||
test:
|
||||
if: ${{ ! startsWith(github.event.head_commit.message, 'release:') && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) }}
|
||||
uses: ./.github/workflows/test.yml
|
||||
|
||||
continuous-release:
|
||||
if: github.repository == 'vuejs/core'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: bahmutov/npm-install@v1
|
||||
- name: Run unit tests
|
||||
run: yarn test --ci
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
test-dts:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: bahmutov/npm-install@v1
|
||||
- name: Run type declaration tests
|
||||
run: yarn test-dts
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
size:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CI_JOB_NUMBER: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: bahmutov/npm-install@v1
|
||||
|
||||
- name: Check build size
|
||||
uses: posva/size-check-action@v1.1.2
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
build_script: size
|
||||
files: packages/vue/dist/vue.global.prod.js packages/runtime-dom/dist/runtime-dom.global.prod.js packages/size-check/dist/size-check.global.prod.js
|
||||
node-version-file: '.node-version'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install deps
|
||||
run: pnpm install
|
||||
|
||||
- name: Build
|
||||
run: pnpm build --withTypes
|
||||
|
||||
- name: Release
|
||||
run: pnpx pkg-pr-new publish --compact --pnpm './packages/*'
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
name: Auto close issues with "can't reproduce" label
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
close-issues:
|
||||
if: github.repository == 'vuejs/core'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: can't reproduce
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'close-issues'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: "can't reproduce"
|
||||
inactive-day: 3
|
|
@ -0,0 +1,90 @@
|
|||
name: ecosystem-ci trigger
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
trigger:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'vuejs/core' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run')
|
||||
steps:
|
||||
- name: Check user permission
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const user = context.payload.sender.login
|
||||
console.log(`Validate user: ${user}`)
|
||||
|
||||
let isVuejsMember = false
|
||||
try {
|
||||
const { status } = await github.rest.orgs.checkMembershipForUser({
|
||||
org: 'vuejs',
|
||||
username: user
|
||||
});
|
||||
|
||||
isVuejsMember = (status === 204)
|
||||
} catch (e) {}
|
||||
|
||||
if (isVuejsMember) {
|
||||
console.log('Allowed')
|
||||
await github.rest.reactions.createForIssueComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: context.payload.comment.id,
|
||||
content: '+1',
|
||||
})
|
||||
} else {
|
||||
console.log('Not allowed')
|
||||
await github.rest.reactions.createForIssueComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: context.payload.comment.id,
|
||||
content: '-1',
|
||||
})
|
||||
throw new Error('not allowed')
|
||||
}
|
||||
- name: Get PR info
|
||||
uses: actions/github-script@v7
|
||||
id: get-pr-data
|
||||
with:
|
||||
script: |
|
||||
console.log(`Get PR info: ${context.repo.owner}/${context.repo.repo}#${context.issue.number}`)
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number
|
||||
})
|
||||
return {
|
||||
num: context.issue.number,
|
||||
branchName: pr.head.ref,
|
||||
repo: pr.head.repo.full_name,
|
||||
commit: pr.head.sha
|
||||
}
|
||||
- name: Trigger run
|
||||
uses: actions/github-script@v7
|
||||
id: trigger
|
||||
env:
|
||||
COMMENT: ${{ github.event.comment.body }}
|
||||
with:
|
||||
github-token: ${{ secrets.ECOSYSTEM_CI_ACCESS_TOKEN }}
|
||||
result-encoding: string
|
||||
script: |
|
||||
const comment = process.env.COMMENT.trim()
|
||||
const prData = ${{ steps.get-pr-data.outputs.result }}
|
||||
|
||||
const suite = comment.replace(/^\/ecosystem-ci run/, '').trim()
|
||||
|
||||
await github.rest.actions.createWorkflowDispatch({
|
||||
owner: context.repo.owner,
|
||||
repo: 'ecosystem-ci',
|
||||
workflow_id: 'ecosystem-ci-from-pr.yml',
|
||||
ref: 'main',
|
||||
inputs: {
|
||||
prNumber: '' + prData.num,
|
||||
branchName: prData.branchName,
|
||||
repo: prData.repo,
|
||||
suite: suite === '' ? '-' : suite,
|
||||
commit: prData.commit
|
||||
}
|
||||
})
|
|
@ -0,0 +1,20 @@
|
|||
name: Lock Closed Issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
action:
|
||||
if: github.repository == 'vuejs/core'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v5
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-inactive-days: '14'
|
||||
issue-lock-reason: ''
|
||||
process-only: 'issues'
|
|
@ -1,23 +0,0 @@
|
|||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
name: Create Release
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@master
|
||||
- name: Create Release for Tag
|
||||
id: release_tag
|
||||
uses: yyx990803/release-tag@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
body: |
|
||||
Please refer to [CHANGELOG.md](https://github.com/vuejs/vue-next/blob/master/CHANGELOG.md) for details.
|
|
@ -0,0 +1,55 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
jobs:
|
||||
test:
|
||||
uses: ./.github/workflows/test.yml
|
||||
|
||||
release:
|
||||
# prevents this action from running on forks
|
||||
if: github.repository == 'vuejs/core'
|
||||
needs: [test]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
# Use Release environment for deployment protection
|
||||
environment: Release
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install deps
|
||||
run: pnpm install
|
||||
|
||||
- name: Build and publish
|
||||
id: publish
|
||||
run: |
|
||||
pnpm release --publishOnly
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Create GitHub release
|
||||
id: release_tag
|
||||
uses: yyx990803/release-tag@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
body: |
|
||||
For stable releases, please refer to [CHANGELOG.md](https://github.com/vuejs/core/blob/main/CHANGELOG.md) for details.
|
||||
For pre-releases, please refer to [CHANGELOG.md](https://github.com/vuejs/core/blob/minor/CHANGELOG.md) of the `minor` branch.
|
|
@ -0,0 +1,51 @@
|
|||
name: size data
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- minor
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- minor
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: 'true'
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
if: github.repository == 'vuejs/core'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- run: pnpm run size
|
||||
|
||||
- name: Save PR number & base branch
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
run: |
|
||||
echo ${{ github.event.number }} > ./temp/size/number.txt
|
||||
echo ${{ github.base_ref }} > ./temp/size/base.txt
|
||||
|
||||
- name: Upload Size Data
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: size-data
|
||||
path: temp/size
|
|
@ -0,0 +1,85 @@
|
|||
name: size report
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ['size data']
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: 'true'
|
||||
|
||||
jobs:
|
||||
size-report:
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
github.repository == 'vuejs/core' &&
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Download Size Data
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
name: size-data
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
path: temp/size
|
||||
|
||||
- name: Read PR Number
|
||||
id: pr-number
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: temp/size/number.txt
|
||||
|
||||
- name: Read base branch
|
||||
id: pr-base
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: temp/size/base.txt
|
||||
|
||||
- name: Download Previous Size Data
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
branch: ${{ steps.pr-base.outputs.content }}
|
||||
workflow: size-data.yml
|
||||
event: push
|
||||
name: size-data
|
||||
path: temp/size-prev
|
||||
if_no_artifact_found: warn
|
||||
|
||||
- name: Prepare report
|
||||
run: pnpm tsx scripts/size-report.ts > size-report.md
|
||||
|
||||
- name: Read Size Report
|
||||
id: size-report
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: ./size-report.md
|
||||
|
||||
- name: Create Comment
|
||||
uses: actions-cool/maintain-one-comment@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
number: ${{ steps.pr-number.outputs.content }}
|
||||
body: |
|
||||
${{ steps.size-report.outputs.content }}
|
||||
<!-- VUE_CORE_SIZE -->
|
||||
body-include: '<!-- VUE_CORE_SIZE -->'
|
|
@ -0,0 +1,108 @@
|
|||
name: 'test'
|
||||
|
||||
on: workflow_call
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
unit-test:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
- run: pnpm install
|
||||
|
||||
- name: Run unit tests
|
||||
run: pnpm run test-unit
|
||||
|
||||
unit-test-windows:
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
- run: pnpm install
|
||||
|
||||
- name: Run compiler unit tests
|
||||
run: pnpm run test-unit compiler
|
||||
|
||||
- name: Run ssr unit tests
|
||||
run: pnpm run test-unit server-renderer
|
||||
|
||||
e2e-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup cache for Chromium binary
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/puppeteer
|
||||
key: chromium-${{ hashFiles('pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
- run: pnpm install
|
||||
- run: node node_modules/puppeteer/install.mjs
|
||||
|
||||
- name: Run e2e tests
|
||||
run: pnpm run test-e2e
|
||||
|
||||
- name: verify treeshaking
|
||||
run: node scripts/verify-treeshaking.js
|
||||
|
||||
lint-and-test-dts:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
- run: pnpm install
|
||||
|
||||
- name: Run eslint
|
||||
run: pnpm run lint
|
||||
|
||||
- name: Run prettier
|
||||
run: pnpm run format-check
|
||||
|
||||
- name: Run type declaration tests
|
||||
run: pnpm run test-dts
|
|
@ -6,3 +6,8 @@ temp
|
|||
explorations
|
||||
TODOs.md
|
||||
*.log
|
||||
.idea
|
||||
.eslintcache
|
||||
dts-build/packages
|
||||
*.tsbuildinfo
|
||||
*.tgz
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
20
|
|
@ -0,0 +1,3 @@
|
|||
dist
|
||||
pnpm-lock.yaml
|
||||
CHANGELOG*.md
|
|
@ -1,3 +1,5 @@
|
|||
semi: false
|
||||
singleQuote: true
|
||||
printWidth: 80
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"recommendations": ["vitest.explorer"]
|
||||
}
|
|
@ -5,24 +5,15 @@
|
|||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Jest",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
||||
"stopOnEntry": false,
|
||||
"args": ["${fileBasename}", "--runInBand", "--detectOpenHandles"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": null,
|
||||
"runtimeExecutable": null,
|
||||
"runtimeArgs": ["--nolazy"],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"console": "integratedTerminal",
|
||||
"sourceMaps": true,
|
||||
"windows": {
|
||||
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
|
||||
}
|
||||
"name": "Vitest - Debug Current Test File",
|
||||
"autoAttachChildProcesses": true,
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
|
||||
"program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
|
||||
"args": ["run", "${relativeFile}"],
|
||||
"smartStep": true,
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<h1 align="center">Sponsors & Backers</h1>
|
||||
|
||||
Vue.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/).
|
||||
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://sponsors.vuejs.org/backers.svg">
|
||||
<img alt="sponsors" src="https://sponsors.vuejs.org/backers.svg?v1">
|
||||
</a>
|
||||
</p>
|
2360
CHANGELOG.md
2360
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"drips": {
|
||||
"ethereum": {
|
||||
"ownedBy": "0x5393BdeA2a020769256d9f337B0fc81a2F64850A"
|
||||
}
|
||||
}
|
||||
}
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-present, Yuxi (Evan) You
|
||||
Copyright (c) 2018-present, Yuxi (Evan) You and Vue contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
126
README.md
126
README.md
|
@ -1,113 +1,53 @@
|
|||
# vue-next [](https://www.npmjs.com/package/vue/v/next) [](https://github.com/vuejs/vue-next/actions/workflows/ci.yml)
|
||||
# vuejs/core [](https://www.npmjs.com/package/vue) [](https://github.com/vuejs/core/actions/workflows/ci.yml) [](https://www.npmjs.com/package/vue)
|
||||
|
||||
This is the repository for Vue 3.0.
|
||||
## Getting Started
|
||||
|
||||
## Quickstart
|
||||
Please follow the documentation at [vuejs.org](https://vuejs.org/)!
|
||||
|
||||
- Via CDN: `<script src="https://unpkg.com/vue@next"></script>`
|
||||
- In-browser playground on [Codepen](https://codepen.io/yyx990803/pen/OJNoaZL)
|
||||
- Scaffold via [Vite](https://github.com/vitejs/vite):
|
||||
## Sponsors
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm init @vitejs/app
|
||||
# yarn
|
||||
yarn create @vitejs/app
|
||||
# select vue template
|
||||
```
|
||||
Vue.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/).
|
||||
|
||||
- Scaffold via [vue-cli](https://cli.vuejs.org/):
|
||||
<p align="center">
|
||||
<h3 align="center">Special Sponsor</h3>
|
||||
</p>
|
||||
|
||||
```bash
|
||||
npm install -g @vue/cli # OR yarn global add @vue/cli
|
||||
vue create hello-vue3
|
||||
# select vue 3 preset
|
||||
```
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://github.com/appwrite/appwrite">
|
||||
<img alt="special sponsor appwrite" src="https://sponsors.vuejs.org/images/appwrite.svg" width="300">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Changes from Vue 2
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://vuejs.org/sponsor/#current-sponsors">
|
||||
<img alt="sponsors" src="https://sponsors.vuejs.org/sponsors.svg?v3">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Please consult the [Migration Guide](https://v3.vuejs.org/guide/migration/introduction.html).
|
||||
## Questions
|
||||
|
||||
Also note: Vue 3 does not support IE11 ([RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0038-vue3-ie11-support.md) | [Discussion](https://github.com/vuejs/rfcs/discussions/296)).
|
||||
For 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.
|
||||
|
||||
## Supporting Libraries
|
||||
## Issues
|
||||
|
||||
All of our official libraries and tools now support Vue 3, but most of them are still in beta status and distributed under the `next` dist tag on NPM. **We are planning to stabilize and switch all projects to use the `latest` dist tag in early 2021.**
|
||||
Please 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.
|
||||
|
||||
### Vue CLI
|
||||
## Stay In Touch
|
||||
|
||||
As of v4.5.0, `vue-cli` now provides built-in option to choose Vue 3 preset when creating a new project. You can upgrade `vue-cli` and run `vue create` to create a Vue 3 project today.
|
||||
- [Twitter](https://twitter.com/vuejs)
|
||||
- [Blog](https://blog.vuejs.org/)
|
||||
- [Job Board](https://vuejobs.com/?ref=vuejs)
|
||||
|
||||
### Vue Router
|
||||
## Contribution
|
||||
|
||||
Vue Router 4.0 provides Vue 3 support and has a number of breaking changes of its own. Check out its [Migration Guide](https://next.router.vuejs.org/guide/migration/) for full details.
|
||||
Please 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)!
|
||||
|
||||
- [](https://www.npmjs.com/package/vue-router/v/next)
|
||||
- [GitHub](https://github.com/vuejs/vue-router-next)
|
||||
- [RFCs](https://github.com/vuejs/rfcs/pulls?q=is%3Apr+is%3Amerged+label%3Arouter)
|
||||
Thank you to all the people who already contributed to Vue!
|
||||
|
||||
### Vuex
|
||||
<a href="https://github.com/vuejs/core/graphs/contributors"><img src="https://opencollective.com/vuejs/contributors.svg?width=890" /></a>
|
||||
|
||||
Vuex 4.0 provides Vue 3 support with largely the same API as 3.x. The only breaking change is [how the plugin is installed](https://github.com/vuejs/vuex/tree/4.0#breaking-changes).
|
||||
## License
|
||||
|
||||
- [](https://www.npmjs.com/package/vuex/v/next)
|
||||
- [GitHub](https://github.com/vuejs/vuex/tree/4.0)
|
||||
[MIT](https://opensource.org/licenses/MIT)
|
||||
|
||||
### Devtools Extension
|
||||
|
||||
We are working on a new version of the Devtools with a new UI and refactored internals to support multiple Vue versions. The new version is currently in beta and only supports Vue 3 (for now). Vuex and Router integration is also work in progress.
|
||||
|
||||
- For Chrome: [Install from Chrome web store](https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg?hl=en)
|
||||
|
||||
- Note: the beta channel may conflict with the stable version of devtools so you may need to temporarily disable the stable version for the beta channel to work properly.
|
||||
|
||||
- For Firefox: [Download the signed extension](https://github.com/vuejs/vue-devtools/releases/tag/v6.0.0-beta.2) (`.xpi` file under Assets)
|
||||
|
||||
### IDE Support
|
||||
|
||||
It is recommended to use [VSCode](https://code.visualstudio.com/). There are currently two viable extensions for Single-File Components (SFCs) support:
|
||||
|
||||
- [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur) (recommended if you are used to Vetur features)
|
||||
- [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) (recommended if using TypeScript with SFCs, or `<script setup>` syntax)
|
||||
|
||||
### TypeScript Support
|
||||
|
||||
- All Vue 3 packages ship with types.
|
||||
- [vue-tsc](https://github.com/johnsoncodehk/vue-tsc) perform TypeScript type checks / diagnostics on Vue SFCs via the command line.
|
||||
- [vue-dts-gen](https://github.com/egoist/vue-dts-gen): generate TypeScript definitions from Vue SFCs.
|
||||
|
||||
### Other Projects
|
||||
|
||||
| Project | NPM | Repo |
|
||||
| --------------------- | ------------------------------- | -------------------- |
|
||||
| @vue/babel-plugin-jsx | [![rc][jsx-badge]][jsx-npm] | [[GitHub][jsx-code]] |
|
||||
| eslint-plugin-vue | [![stable][epv-badge]][epv-npm] | [[GitHub][epv-code]] |
|
||||
| @vue/test-utils | [![beta][vtu-badge]][vtu-npm] | [[GitHub][vtu-code]] |
|
||||
| vue-class-component | [![beta][vcc-badge]][vcc-npm] | [[GitHub][vcc-code]] |
|
||||
| vue-loader | [![beta][vl-badge]][vl-npm] | [[GitHub][vl-code]] |
|
||||
| rollup-plugin-vue | [![beta][rpv-badge]][rpv-npm] | [[GitHub][rpv-code]] |
|
||||
|
||||
[jsx-badge]: https://img.shields.io/npm/v/@vue/babel-plugin-jsx.svg
|
||||
[jsx-npm]: https://www.npmjs.com/package/@vue/babel-plugin-jsx
|
||||
[jsx-code]: https://github.com/vuejs/jsx-next
|
||||
[vd-badge]: https://img.shields.io/npm/v/@vue/devtools/beta.svg
|
||||
[vd-npm]: https://www.npmjs.com/package/@vue/devtools/v/beta
|
||||
[vd-code]: https://github.com/vuejs/vue-devtools/tree/next
|
||||
[epv-badge]: https://img.shields.io/npm/v/eslint-plugin-vue.svg
|
||||
[epv-npm]: https://www.npmjs.com/package/eslint-plugin-vue
|
||||
[epv-code]: https://github.com/vuejs/eslint-plugin-vue
|
||||
[vtu-badge]: https://img.shields.io/npm/v/@vue/test-utils/next.svg
|
||||
[vtu-npm]: https://www.npmjs.com/package/@vue/test-utils/v/next
|
||||
[vtu-code]: https://github.com/vuejs/vue-test-utils-next
|
||||
[jsx-badge]: https://img.shields.io/npm/v/@ant-design-vue/babel-plugin-jsx.svg
|
||||
[jsx-npm]: https://www.npmjs.com/package/@ant-design-vue/babel-plugin-jsx
|
||||
[jsx-code]: https://github.com/vueComponent/jsx
|
||||
[vcc-badge]: https://img.shields.io/npm/v/vue-class-component/next.svg
|
||||
[vcc-npm]: https://www.npmjs.com/package/vue-class-component/v/next
|
||||
[vcc-code]: https://github.com/vuejs/vue-class-component/tree/next
|
||||
[vl-badge]: https://img.shields.io/npm/v/vue-loader/next.svg
|
||||
[vl-npm]: https://www.npmjs.com/package/vue-loader/v/next
|
||||
[vl-code]: https://github.com/vuejs/vue-loader/tree/next
|
||||
[rpv-badge]: https://img.shields.io/npm/v/rollup-plugin-vue/next.svg
|
||||
[rpv-npm]: https://www.npmjs.com/package/rollup-plugin-vue/v/next
|
||||
[rpv-code]: https://github.com/vuejs/rollup-plugin-vue/tree/next
|
||||
Copyright (c) 2013-present, Yuxi (Evan) You
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# Reporting a Vulnerability
|
||||
|
||||
To report a vulnerability, please email security@vuejs.org.
|
||||
|
||||
While 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.
|
||||
|
||||
Please 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.
|
||||
|
||||
## Security Hall of Fame
|
||||
|
||||
We would like to thank the following security researchers for responsibly disclosing security issues to us.
|
||||
|
||||
- Jeet Pal - [@jeetpal2007](https://github.com/jeetpal2007) | [Email](mailto:jeetpal2007@gmail.com) | [LinkedIn](https://in.linkedin.com/in/jeet-pal-22601a290)
|
||||
- Mix - [@mnixry](https://github.com/mnixry)
|
||||
- Aviv Keller - [@RedYetiDev](https://github.com/redyetidev) | [LinkedIn](https://www.linkedin.com/in/redyetidev) <redyetidev@gmail.com>
|
|
@ -1,50 +0,0 @@
|
|||
// this the shared base config for all packages.
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
|
||||
"apiReport": {
|
||||
"enabled": true,
|
||||
"reportFolder": "<projectFolder>/temp/"
|
||||
},
|
||||
|
||||
"docModel": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
"dtsRollup": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
"tsdocMetadata": {
|
||||
"enabled": false
|
||||
},
|
||||
|
||||
"messages": {
|
||||
"compilerMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
}
|
||||
},
|
||||
|
||||
"extractorMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning",
|
||||
"addToApiReportFile": true
|
||||
},
|
||||
|
||||
"ae-missing-release-tag": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
},
|
||||
|
||||
"tsdocMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
},
|
||||
|
||||
"tsdoc-undefined-tag": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,320 @@
|
|||
## [3.1.5](https://github.com/vuejs/core/compare/v3.1.4...v3.1.5) (2021-07-16)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **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))
|
||||
- **compat:** fix v3 compiled fn detection in production ([8dbad83](https://github.com/vuejs/core/commit/8dbad83e7fa39be3e61ca694a6090c1646117953))
|
||||
- **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)
|
||||
- **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)
|
||||
- **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))
|
||||
- **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)
|
||||
- **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)
|
||||
- **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))
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
|
||||
## [3.1.4](https://github.com/vuejs/core/compare/v3.1.3...v3.1.4) (2021-07-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **build:** avoid using async/await syntax ([438754a](https://github.com/vuejs/core/commit/438754a0d1428d10e27d1a290beb4b81da5fdaeb))
|
||||
- **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)
|
||||
- **codegen:** ensure valid types in genreated code when using global directives ([a44d528](https://github.com/vuejs/core/commit/a44d528af1227c05dedf610b6ec45504d8e58276)), closes [#4054](https://github.com/vuejs/core/issues/4054)
|
||||
- **compiler-sfc:** fix parse-only mode when there is no script setup block ([253ca27](https://github.com/vuejs/core/commit/253ca2729d808fc051215876aa4af986e4caa43c))
|
||||
- **runtime-core:** add useAttrs and useSlots export ([#4053](https://github.com/vuejs/core/issues/4053)) ([735ada1](https://github.com/vuejs/core/commit/735ada1507623b8d36e80b30a4f67a8af4a45c99))
|
||||
- **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))
|
||||
|
||||
## [3.1.3](https://github.com/vuejs/core/compare/v3.1.2...v3.1.3) (2021-07-01)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **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)
|
||||
- **compiler-sfc:** avoid script setup marker showing up in devtools ([211793d](https://github.com/vuejs/core/commit/211793d3767b12dd457de62160b672af24b921e7))
|
||||
- **compiler-sfc:** fix defineProps() call on imported identifier ([691d354](https://github.com/vuejs/core/commit/691d354af9e3a66c781494656b367950fcd8faec))
|
||||
- **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)
|
||||
- **compiler-sfc:** fix script setup hidden flag codegen ([a5a66c5](https://github.com/vuejs/core/commit/a5a66c5196f5e00e8cbf7f6008d350d6eabcee71))
|
||||
- **compiler-sfc:** support method signature in defineProps ([afdd2f2](https://github.com/vuejs/core/commit/afdd2f28354ce8cea647279ed25d61e7b9946cf5)), closes [#2983](https://github.com/vuejs/core/issues/2983)
|
||||
- **compiler-sfc:** support TS runtime enum in `<script setup>` ([1ffd48a](https://github.com/vuejs/core/commit/1ffd48a2f5fd3eead3ea29dae668b7ed1c6f6130))
|
||||
- **runtime-core:** add missing serverPrefetch hook error string ([#4014](https://github.com/vuejs/core/issues/4014)) ([d069796](https://github.com/vuejs/core/commit/d069796b8f0cf8df9aa77d781c4b5429b9411204))
|
||||
- **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)
|
||||
- **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)
|
||||
- **sfc:** allow variables that start with \_ or $ in `<script setup>` ([0b8b576](https://github.com/vuejs/core/commit/0b8b5764287b4814a37034ad4bc6f2b8ac8f8700))
|
||||
- **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)
|
||||
- **ssr:** properly hydrate non-string value bindings ([34d4991](https://github.com/vuejs/core/commit/34d4991dd5876325eb8747afa9a835929bde3974)), closes [#4006](https://github.com/vuejs/core/issues/4006)
|
||||
- **types:** improve type of unref() ([127ed1b](https://github.com/vuejs/core/commit/127ed1b969cb2d237d0f588aab726e04f4732641)), closes [#3954](https://github.com/vuejs/core/issues/3954)
|
||||
- defineExpose type definition and runtime warning ([1675b6d](https://github.com/vuejs/core/commit/1675b6d723829d1f61e697735e3da7b16aa1362d))
|
||||
- prevent withAsyncContext currentInstance leak in edge cases ([9ee41e1](https://github.com/vuejs/core/commit/9ee41e14d2d173866300e75758468c6788180277))
|
||||
|
||||
### Features
|
||||
|
||||
- **compiler-sfc:** compileScript parseOnly mode ([601a290](https://github.com/vuejs/core/commit/601a290caaf7fa29c58c88ac79fc2f1d2c57e337))
|
||||
- **expose:** always expose $ instance properties on child refs ([b0203a3](https://github.com/vuejs/core/commit/b0203a30929e4e7f59e035574e43d72ed3b9d7fd))
|
||||
- **sfc:** add `defineEmits` and deprecate `defineEmit` ([#3725](https://github.com/vuejs/core/issues/3725)) ([a137da8](https://github.com/vuejs/core/commit/a137da8a9f728edacd50d288bce281e32597197b))
|
||||
- **sfc:** auto restore current instance after await statements in async setup() ([0240e82](https://github.com/vuejs/core/commit/0240e82a38e2e0c5f0b63c228fd02b059a19073d))
|
||||
- **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)
|
||||
- **sfc:** defineExpose ([be2b1d3](https://github.com/vuejs/core/commit/be2b1d3c2f16de8dc6e2a22f65fefaa2d25ec3ee))
|
||||
- **sfc:** make ref sugar disabled by default ([96cc335](https://github.com/vuejs/core/commit/96cc335aa7050b6bf2ae53cc209d0032a8d59d0e))
|
||||
- **sfc:** remove `<template inherit-attrs>` support ([6f6f0cf](https://github.com/vuejs/core/commit/6f6f0cf5dcc02f4a648fab86439eb29a4b5596d2))
|
||||
- **sfc:** support referenced types for defineEmits ([2973b6c](https://github.com/vuejs/core/commit/2973b6c30ae5b3ff65aeb71a26a6de1c7789537d))
|
||||
- **sfc:** support using declared interface or type alias with defineProps() ([2f91db3](https://github.com/vuejs/core/commit/2f91db30cda5c315ed3e4d20800b55721b0cb17c))
|
||||
- **sfc:** useAttrs + useSlots ([63e9e2e](https://github.com/vuejs/core/commit/63e9e2e9aae07c701548f3350ea83535bea22066))
|
||||
- **sfc:** withDefaults helper ([4c5844a](https://github.com/vuejs/core/commit/4c5844a9ca0acc4ea45565a0dc9a21c2502d64a4))
|
||||
- **sfc-playground:** support lang=ts ([be0f614](https://github.com/vuejs/core/commit/be0f614ac096bdfe44cfddb04c859c9747dcd6dd))
|
||||
- **sfc/types:** make `<script setup>` helper types available globally ([004bd18](https://github.com/vuejs/core/commit/004bd18cf75526bd79f68ccea8102aa94a8a28e2))
|
||||
- **types:** support IDE renaming for props ([#3656](https://github.com/vuejs/core/issues/3656)) ([81e69b2](https://github.com/vuejs/core/commit/81e69b29ecf992d215d8ddc56bf7e40661144595))
|
||||
- **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))
|
||||
|
||||
## [3.1.2](https://github.com/vuejs/core/compare/v3.1.1...v3.1.2) (2021-06-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **compiler-core:** improve member expression check ([bc100c5](https://github.com/vuejs/core/commit/bc100c5c48b98b6e2eabfa1d50e0d3099ea2a90d)), closes [#3910](https://github.com/vuejs/core/issues/3910)
|
||||
- **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)
|
||||
- **compiler-sfc:** rewriteDefault support multiline ([#3917](https://github.com/vuejs/core/issues/3917)) ([b228abb](https://github.com/vuejs/core/commit/b228abb72fcdb4fc9dced907f3614abcaaacdce5))
|
||||
- **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)
|
||||
- **devtools:** expose root instance ([2b52d5d](https://github.com/vuejs/core/commit/2b52d5d7c53f7843f4a1e85fd7f1720dc2847ebc))
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **watch:** fix watch option merging from mixins ([9b607fe](https://github.com/vuejs/core/commit/9b607fe409d70e991ba458e7c994e008a4b621e8)), closes [#3966](https://github.com/vuejs/core/issues/3966)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- improve static content insertion perf ([4de5d24](https://github.com/vuejs/core/commit/4de5d24aa72f6bc68da967ead330147032983e30)), closes [#3090](https://github.com/vuejs/core/issues/3090)
|
||||
|
||||
## [3.1.1](https://github.com/vuejs/core/compare/v3.1.0...v3.1.1) (2021-06-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **compat:** update cjs dist file names ([#3893](https://github.com/vuejs/core/issues/3893)) ([434ea30](https://github.com/vuejs/core/commit/434ea30505466bceb433f113d84f4b4ef8866047))
|
||||
|
||||
# [3.1.0](https://github.com/vuejs/core/compare/v3.1.0-beta.7...v3.1.0) (2021-06-07)
|
||||
|
||||
### Features
|
||||
|
||||
- [Migration Build](https://v3-migration.vuejs.org/migration-build.html)
|
||||
- **compiler-core:** whitespace handling strategy ([dee3d6a](https://github.com/vuejs/core/commit/dee3d6ab8b4da6653d15eb148c51d9878007f6b6))
|
||||
- support component-level `compilerOptions` when using runtime compiler ([ce0bbe0](https://github.com/vuejs/core/commit/ce0bbe053abaf8ba18de8baf535e175048596ee5))
|
||||
- **config:** support configuring runtime compiler via `app.config.compilerOptions` ([091e6d6](https://github.com/vuejs/core/commit/091e6d67bfcc215227d78be578c68ead542481ad))
|
||||
- support casting plain element to component via is="vue:xxx" ([af9e699](https://github.com/vuejs/core/commit/af9e6999e1779f56b5cf827b97310d8e4e1fe5ec))
|
||||
- **devtools:** improved KeepAlive support ([03ae300](https://github.com/vuejs/core/commit/03ae3006e1e678ade4377cd10d206e8f7b4ad0cb))
|
||||
- **devtools:** performance events ([f7c54ca](https://github.com/vuejs/core/commit/f7c54caeb1dac69a26b79c98409e9633a7fe4bd3))
|
||||
- onServerPrefetch ([#3070](https://github.com/vuejs/core/issues/3070)) ([349eb0f](https://github.com/vuejs/core/commit/349eb0f0ad78f9cb491278eb4c7f9fe0c2e78b79))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- only trigger `$attrs` update when it has actually changed ([5566d39](https://github.com/vuejs/core/commit/5566d39d467ebdd4e4234bc97d62600ff01ea28e))
|
||||
- **compiler:** skip unncessary checks when parsing end tag ([048ac29](https://github.com/vuejs/core/commit/048ac299f35709b25ae1bc1efa67d2abc53dbc3b))
|
||||
- avoid deopt for props/emits normalization when global mixins are used ([51d2be2](https://github.com/vuejs/core/commit/51d2be20386d4dc59006d31a1cc96676871027ce))
|
||||
|
||||
### Deprecations
|
||||
|
||||
- `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)]
|
||||
- `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)]
|
||||
- `v-is` has been deprecated in favor of `is="vue:xxx"` [[Docs](https://v3.vuejs.org/api/special-attributes.html#is)]
|
||||
|
||||
### Minor Breaking Changes
|
||||
|
||||
- `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:
|
||||
|
||||
```js
|
||||
const isAbsent = Symbol()
|
||||
|
||||
export default {
|
||||
props: {
|
||||
foo: { default: isAbsent }
|
||||
},
|
||||
setup(props) {
|
||||
if (props.foo === isAbsent) {
|
||||
// foo is absent
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `optionMergeStrategies` functions no longer receive
|
||||
the component instance as the 3rd argument. The argument was technically
|
||||
internal in Vue 2 and only used for generating warnings, and should not
|
||||
be needed in userland code. This removal enables much more efficient
|
||||
caching of option merging.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **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)
|
||||
- **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)
|
||||
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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))
|
||||
* **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)
|
||||
* **watch:** avoid traversing objects that are marked non-reactive ([9acc9a1](https://github.com/vuejs/core/commit/9acc9a1fa838bdcdf673d2f7cc3f996b2b69ffbc))
|
||||
* **compiler-core:** improve the isMemberExpression function ([#3675](https://github.com/vuejs/core/issues/3675)) ([9b2e894](https://github.com/vuejs/core/commit/9b2e8940176b3b75fa052b3c3e9eeaabc46a95e6))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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))
|
||||
* **runtime-core:** stricter compat root mount check ([32e2133](https://github.com/vuejs/core/commit/32e21333dd1197a978cf42802729b2133bda5a0b))
|
||||
* **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))
|
||||
* **suspense:** fix suspense patching in optimized mode ([9f24195](https://github.com/vuejs/core/commit/9f24195d2ce24184ccdc5020793dd9423f0d3148)), closes [#3828](https://github.com/vuejs/core/issues/3828)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **compat:** avoid accidentally delete the modelValue prop ([#3772](https://github.com/vuejs/core/issues/3772)) ([4f17be7](https://github.com/vuejs/core/commit/4f17be7b1ce4872ded085a36b95c1897d8c1f299))
|
||||
* **compat:** enum coercion warning ([#3755](https://github.com/vuejs/core/issues/3755)) ([f01aadf](https://github.com/vuejs/core/commit/f01aadf2a16a7bef422eb039d7b157bef9ad32fc))
|
||||
* **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)
|
||||
* **compiler-dom:** comments in the v-if branchs 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)
|
||||
* **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)
|
||||
* **compiler-ssr:** disable hoisting in compiler-ssr ([3ef1fcc](https://github.com/vuejs/core/commit/3ef1fcc8590da186664197a0a82e7856011c1693)), closes [#3536](https://github.com/vuejs/core/issues/3536)
|
||||
* **devtools:** send update to component owning the slot ([1355ee2](https://github.com/vuejs/core/commit/1355ee27a65d466bfe8f3a7ba99aa2213e25bc50))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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))
|
||||
* **types/reactivity:** error TS4058 caused by `RefSymbol` ([#2548](https://github.com/vuejs/core/issues/2548)) ([90aa835](https://github.com/vuejs/core/commit/90aa8358129f25826bfc4c234325c1442aef8d55))
|
||||
* **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)
|
||||
* **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))
|
||||
* **compat:** handle and warn config.optionMergeStrategies ([94e69fd](https://github.com/vuejs/core/commit/94e69fd3896214da6ff8b9fb09ad942c598053c7))
|
||||
* **compiler-core:** preserve comment content in production when comments option is enabled ([e486254](https://github.com/vuejs/core/commit/e4862544310a4187dfc8b3a49944700888bb60e3))
|
||||
* **hmr:** don't remove \_\_file key from component type ([9db3cbb](https://github.com/vuejs/core/commit/9db3cbbfc1a072675a8d0e53edf3869af115dc60))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **watch:** avoid traversing non-plain objects ([62b8f4a](https://github.com/vuejs/core/commit/62b8f4a39ca56b48a8c8fdf7e200cb80735e16ae))
|
||||
* **watch:** this.$watch should support watching keypath ([870f2a7](https://github.com/vuejs/core/commit/870f2a7ba35245fd8c008d2ff666ea130a7e4704))
|
||||
|
||||
# [3.1.0-beta.7](https://github.com/vuejs/core/compare/v3.1.0-beta.6...v3.1.0-beta.7) (2021-06-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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))
|
||||
- **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)
|
||||
- **watch:** avoid traversing objects that are marked non-reactive ([9acc9a1](https://github.com/vuejs/core/commit/9acc9a1fa838bdcdf673d2f7cc3f996b2b69ffbc))
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
- adjust component options merge cache strategy ([1e35a86](https://github.com/vuejs/core/commit/1e35a860b995c1158d5c4e1706d2fc9bcd3b8412))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- avoid deopt for props/emits normalization when global mixins are used ([51d2be2](https://github.com/vuejs/core/commit/51d2be20386d4dc59006d31a1cc96676871027ce))
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- optionMergeStrategies functions no longer receive
|
||||
the component instance as the 3rd argument. The argument was technically
|
||||
internal in Vue 2 and only used for generating warnings, and should not
|
||||
be needed in userland code. This removal enables much more efficient
|
||||
caching of option merging.
|
||||
|
||||
# [3.1.0-beta.6](https://github.com/vuejs/core/compare/v3.1.0-beta.5...v3.1.0-beta.6) (2021-05-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **compiler-core:** improve the isMemberExpression function ([#3675](https://github.com/vuejs/core/issues/3675)) ([9b2e894](https://github.com/vuejs/core/commit/9b2e8940176b3b75fa052b3c3e9eeaabc46a95e6))
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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))
|
||||
- **runtime-core:** stricter compat root mount check ([32e2133](https://github.com/vuejs/core/commit/32e21333dd1197a978cf42802729b2133bda5a0b))
|
||||
- **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))
|
||||
- **suspense:** fix suspense patching in optimized mode ([9f24195](https://github.com/vuejs/core/commit/9f24195d2ce24184ccdc5020793dd9423f0d3148)), closes [#3828](https://github.com/vuejs/core/issues/3828)
|
||||
- **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)
|
||||
|
||||
# [3.1.0-beta.5](https://github.com/vuejs/core/compare/v3.1.0-beta.4...v3.1.0-beta.5) (2021-05-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
|
||||
# [3.1.0-beta.4](https://github.com/vuejs/core/compare/v3.1.0-beta.3...v3.1.0-beta.4) (2021-05-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **compat:** avoid accidentally delete the modelValue prop ([#3772](https://github.com/vuejs/core/issues/3772)) ([4f17be7](https://github.com/vuejs/core/commit/4f17be7b1ce4872ded085a36b95c1897d8c1f299))
|
||||
- **compat:** enum coercion warning ([#3755](https://github.com/vuejs/core/issues/3755)) ([f01aadf](https://github.com/vuejs/core/commit/f01aadf2a16a7bef422eb039d7b157bef9ad32fc))
|
||||
- **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)
|
||||
- **compiler-dom:** comments in the v-if branchs 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)
|
||||
- **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)
|
||||
- **compiler-ssr:** disable hoisting in compiler-ssr ([3ef1fcc](https://github.com/vuejs/core/commit/3ef1fcc8590da186664197a0a82e7856011c1693)), closes [#3536](https://github.com/vuejs/core/issues/3536)
|
||||
- **devtools:** send update to component owning the slot ([1355ee2](https://github.com/vuejs/core/commit/1355ee27a65d466bfe8f3a7ba99aa2213e25bc50))
|
||||
- **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)
|
||||
- **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)
|
||||
- **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))
|
||||
- **types/reactivity:** error TS4058 caused by `RefSymbol` ([#2548](https://github.com/vuejs/core/issues/2548)) ([90aa835](https://github.com/vuejs/core/commit/90aa8358129f25826bfc4c234325c1442aef8d55))
|
||||
|
||||
### Features
|
||||
|
||||
- **devtools:** performance events ([f7c54ca](https://github.com/vuejs/core/commit/f7c54caeb1dac69a26b79c98409e9633a7fe4bd3))
|
||||
|
||||
# [3.1.0-beta.3](https://github.com/vuejs/core/compare/v3.1.0-beta.2...v3.1.0-beta.3) (2021-05-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **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)
|
||||
- **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))
|
||||
|
||||
# [3.1.0-beta.2](https://github.com/vuejs/core/compare/v3.1.0-beta.1...v3.1.0-beta.2) (2021-05-08)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **compat:** handle and warn config.optionMergeStrategies ([94e69fd](https://github.com/vuejs/core/commit/94e69fd3896214da6ff8b9fb09ad942c598053c7))
|
||||
|
||||
# [3.1.0-beta.1](https://github.com/vuejs/core/compare/v3.0.11...v3.1.0-beta.1) (2021-05-08)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **compiler-core:** preserve comment content in production when comments option is enabled ([e486254](https://github.com/vuejs/core/commit/e4862544310a4187dfc8b3a49944700888bb60e3))
|
||||
- **hmr:** don't remove \_\_file key from component type ([9db3cbb](https://github.com/vuejs/core/commit/9db3cbbfc1a072675a8d0e53edf3869af115dc60))
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **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)
|
||||
- **watch:** avoid traversing non-plain objects ([62b8f4a](https://github.com/vuejs/core/commit/62b8f4a39ca56b48a8c8fdf7e200cb80735e16ae))
|
||||
- **watch:** this.$watch should support watching keypath ([870f2a7](https://github.com/vuejs/core/commit/870f2a7ba35245fd8c008d2ff666ea130a7e4704))
|
||||
|
||||
### Features
|
||||
|
||||
- onServerPrefetch ([#3070](https://github.com/vuejs/core/issues/3070)) ([349eb0f](https://github.com/vuejs/core/commit/349eb0f0ad78f9cb491278eb4c7f9fe0c2e78b79))
|
||||
- support component-level `compilerOptions` when using runtime compiler ([ce0bbe0](https://github.com/vuejs/core/commit/ce0bbe053abaf8ba18de8baf535e175048596ee5))
|
||||
- **compiler-core:** whitespace handling strategy ([dee3d6a](https://github.com/vuejs/core/commit/dee3d6ab8b4da6653d15eb148c51d9878007f6b6))
|
||||
- **config:** support configuring runtime compiler via `app.config.compilerOptions` ([091e6d6](https://github.com/vuejs/core/commit/091e6d67bfcc215227d78be578c68ead542481ad))
|
||||
- **devtools:** improved KeepAlive support ([03ae300](https://github.com/vuejs/core/commit/03ae3006e1e678ade4377cd10d206e8f7b4ad0cb))
|
||||
- support casting plain element to component via is="vue:xxx" ([af9e699](https://github.com/vuejs/core/commit/af9e6999e1779f56b5cf827b97310d8e4e1fe5ec))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- only trigger $attrs update when it has actually changed ([5566d39](https://github.com/vuejs/core/commit/5566d39d467ebdd4e4234bc97d62600ff01ea28e))
|
||||
- **compiler:** skip unncessary checks when parsing end tag ([048ac29](https://github.com/vuejs/core/commit/048ac299f35709b25ae1bc1efa67d2abc53dbc3b))
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,598 @@
|
|||
## [3.3.13](https://github.com/vuejs/core/compare/v3.3.12...v3.3.13) (2023-12-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
## [3.3.12](https://github.com/vuejs/core/compare/v3.3.11...v3.3.12) (2023-12-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **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)
|
||||
* **ssr:** fix suspense hydration of fallback content ([#7188](https://github.com/vuejs/core/issues/7188)) ([60415b5](https://github.com/vuejs/core/commit/60415b5d67df55f1fd6b176615299c08640fa142))
|
||||
* **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)
|
||||
* **types:** fix `shallowRef` type error ([#9839](https://github.com/vuejs/core/issues/9839)) ([9a57158](https://github.com/vuejs/core/commit/9a571582b53220270e498d8712ea59312c0bef3a))
|
||||
* **types:** support for generic keyof slots ([#8374](https://github.com/vuejs/core/issues/8374)) ([213eba4](https://github.com/vuejs/core/commit/213eba479ce080efc1053fe636f6be4a4c889b44))
|
||||
|
||||
|
||||
|
||||
## [3.3.11](https://github.com/vuejs/core/compare/v3.3.10...v3.3.11) (2023-12-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **shared:** handle more Symbol cases in toDisplayString ([983d45d](https://github.com/vuejs/core/commit/983d45d4f8eb766b5a16b7ea93b86d3c51618fa6))
|
||||
* **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)
|
||||
* **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))
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
## [3.3.10](https://github.com/vuejs/core/compare/v3.3.9...v3.3.10) (2023-12-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **compiler-sfc:** avoid passing forEach index to genMap ([f12db7f](https://github.com/vuejs/core/commit/f12db7fb564a534cef2e5805cc9f54afe5d72fbf))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **compiler-sfc:** support resolving components from props ([#8785](https://github.com/vuejs/core/issues/8785)) ([7cbcee3](https://github.com/vuejs/core/commit/7cbcee3d831241a8bd3588ae92d3f27e3641e25f))
|
||||
* **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))
|
||||
* **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)
|
||||
* **deps:** update compiler to ^7.23.4 ([#9681](https://github.com/vuejs/core/issues/9681)) ([31f6ebc](https://github.com/vuejs/core/commit/31f6ebc4df84490ed29fb75e7bf4259200eb51f0))
|
||||
* **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)
|
||||
* **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))
|
||||
* **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)
|
||||
* **types:** expose emits as props in functional components ([#9234](https://github.com/vuejs/core/issues/9234)) ([887e54c](https://github.com/vuejs/core/commit/887e54c347ea9eac4c721b5e2288f054873d1d30))
|
||||
* **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)
|
||||
* **types:** improve return type withKeys and withModifiers ([#9734](https://github.com/vuejs/core/issues/9734)) ([43c3cfd](https://github.com/vuejs/core/commit/43c3cfdec5ae5d70fa2a21e857abc2d73f1a0d07))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* optimize on* prop check ([38aaa8c](https://github.com/vuejs/core/commit/38aaa8c88648c54fe2616ad9c0961288092fcb44))
|
||||
* **runtime-dom:** cache modifier wrapper functions ([da4a4fb](https://github.com/vuejs/core/commit/da4a4fb5e8eee3c6d31f24ebd79a9d0feca56cb2)), closes [#8882](https://github.com/vuejs/core/issues/8882)
|
||||
* **v-on:** constant handlers with modifiers should not be treated as dynamic ([4d94ebf](https://github.com/vuejs/core/commit/4d94ebfe75174b340d2b794e699cad1add3600a9))
|
||||
|
||||
|
||||
|
||||
## [3.3.9](https://github.com/vuejs/core/compare/v3.3.8...v3.3.9) (2023-11-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **hydration:** properly hydrate indeterminate prop ([34b5a5d](https://github.com/vuejs/core/commit/34b5a5da4ae9c9faccac237acd7acc8e7e017571)), closes [#7476](https://github.com/vuejs/core/issues/7476)
|
||||
* **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))
|
||||
* **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)
|
||||
* **ssr:** hydration `__vnode` missing for devtools ([#9328](https://github.com/vuejs/core/issues/9328)) ([5156ac5](https://github.com/vuejs/core/commit/5156ac5b38cfa80d3db26f2c9bf40cb22a7521cb))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **types:** more precise types for class bindings ([#8012](https://github.com/vuejs/core/issues/8012)) ([46e3374](https://github.com/vuejs/core/commit/46e33744c890bd49482c5e5c5cdea44e00ec84d5))
|
||||
* **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)
|
||||
* **types:** return type of withDefaults should be readonly ([#8601](https://github.com/vuejs/core/issues/8601)) ([f15debc](https://github.com/vuejs/core/commit/f15debc01acb22d23f5acee97e6f02db88cef11a))
|
||||
* **types:** revert class type restrictions ([5d077c8](https://github.com/vuejs/core/commit/5d077c8754cc14f85d2d6d386df70cf8c0d93842)), closes [#8012](https://github.com/vuejs/core/issues/8012)
|
||||
* **types:** update jsx type definitions ([#8607](https://github.com/vuejs/core/issues/8607)) ([58e2a94](https://github.com/vuejs/core/commit/58e2a94871ae06a909c5f8bad07fb401193e6a38))
|
||||
* **types:** widen ClassValue type ([2424013](https://github.com/vuejs/core/commit/242401305944422d0c361b16101a4d18908927af))
|
||||
* **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)
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
## [3.3.8](https://github.com/vuejs/core/compare/v3.3.7...v3.3.8) (2023-11-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compile-sfc:** support `Error` type in `defineProps` ([#5955](https://github.com/vuejs/core/issues/5955)) ([a989345](https://github.com/vuejs/core/commit/a9893458ec519aae442e1b99e64e6d74685cd22c))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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))
|
||||
* **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))
|
||||
* **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)
|
||||
* **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)
|
||||
* **warn:** avoid warning on empty children with Suspense ([#3962](https://github.com/vuejs/core/issues/3962)) ([405f345](https://github.com/vuejs/core/commit/405f34587a63a5f1e3d147b9848219ea98acc22d))
|
||||
|
||||
|
||||
|
||||
## [3.3.7](https://github.com/vuejs/core/compare/v3.3.6...v3.3.7) (2023-10-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **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)
|
||||
* 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)
|
||||
* **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)
|
||||
* **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))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
## [3.3.6](https://github.com/vuejs/core/compare/v3.3.5...v3.3.6) (2023-10-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-sfc:** model name conflict ([#8798](https://github.com/vuejs/core/issues/8798)) ([df81da8](https://github.com/vuejs/core/commit/df81da8be97c8a1366563c7e3e01076ef02eb8f7))
|
||||
* **compiler-sfc:** support asset paths containing spaces ([#8752](https://github.com/vuejs/core/issues/8752)) ([36c99a9](https://github.com/vuejs/core/commit/36c99a9c6bb6bc306be054c3c8a85ff8ce50605a))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **types:** support contenteditable="plaintext-only" ([#8796](https://github.com/vuejs/core/issues/8796)) ([26ca89e](https://github.com/vuejs/core/commit/26ca89e5cf734fbef81e182050d2a215ec8a437b))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* replace Map/Set with WeakMap/WeakSet ([#8549](https://github.com/vuejs/core/issues/8549)) ([712f96d](https://github.com/vuejs/core/commit/712f96d6ac4d3d984732cba448cb84624daba850))
|
||||
|
||||
|
||||
|
||||
## [3.3.5](https://github.com/vuejs/core/compare/v3.3.4...v3.3.5) (2023-10-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 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)
|
||||
* **build:** disable useDefineForClassFields in esbuild ([#9252](https://github.com/vuejs/core/issues/9252)) ([6d14fa8](https://github.com/vuejs/core/commit/6d14fa88e85d4c9e264be394ddb37a54ca6738a8))
|
||||
* **compat:** return value of vue compat set() ([#9377](https://github.com/vuejs/core/issues/9377)) ([e3c2d69](https://github.com/vuejs/core/commit/e3c2d699f694d9500ddee78571172a24f0e3b17a))
|
||||
* **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)
|
||||
* **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))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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))
|
||||
* **compiler-sfc:** pass options directly to stylus ([#3848](https://github.com/vuejs/core/issues/3848)) ([d6446a6](https://github.com/vuejs/core/commit/d6446a6d40774b79045a9ddba7b5fd5201d51450))
|
||||
* **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)
|
||||
* **compiler-sfc:** typo in experimental feature warnings ([#8513](https://github.com/vuejs/core/issues/8513)) ([fd1a3f9](https://github.com/vuejs/core/commit/fd1a3f95990d7c372fa1c0c40c55caca761a33a4))
|
||||
* **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))
|
||||
* **deps:** update playground ([#9154](https://github.com/vuejs/core/issues/9154)) ([c8566a2](https://github.com/vuejs/core/commit/c8566a22b7cf37e6aefab7bad7b97ce2db9fae4c))
|
||||
* **playground:** fix github button style ([#7722](https://github.com/vuejs/core/issues/7722)) ([5ee992c](https://github.com/vuejs/core/commit/5ee992cfeabc6c4b871980c6057d0ac7140ad2fa))
|
||||
* **runtime-core:** swap client/server debug labels ([#9089](https://github.com/vuejs/core/issues/9089)) ([8f311c6](https://github.com/vuejs/core/commit/8f311c6f823f6776ca1c49bfbbbf8c7d9dea9cf1))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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))
|
||||
* **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))
|
||||
* **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))
|
||||
* **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))
|
||||
* **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))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-sfc:** lazy require typescript ([d2c3d8b](https://github.com/vuejs/core/commit/d2c3d8b70b2df6e16f053a7ac58e6b04e7b2078f))
|
||||
* **custom-element:** cancel `MutationObserver` listener when disconnected ([#8666](https://github.com/vuejs/core/issues/8666)) ([24d98f0](https://github.com/vuejs/core/commit/24d98f03276de5b0fbced5a4c9d61b24e7d9d084))
|
||||
* mark `defineComponent` as side-effects-free ([#8512](https://github.com/vuejs/core/issues/8512)) ([438027c](https://github.com/vuejs/core/commit/438027cf9ecb63260f59d3027e0b188717694795))
|
||||
|
||||
|
||||
|
||||
## [3.3.4](https://github.com/vuejs/core/compare/v3.3.3...v3.3.4) (2023-05-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **build:** ensure correct typing for node esm ([d621d4c](https://github.com/vuejs/core/commit/d621d4c646b2d7b190fbd44ad1fd04512b3de300))
|
||||
* **build:** fix __DEV__ flag replacement edge case ([8b7c04b](https://github.com/vuejs/core/commit/8b7c04b18f73aad9a08dd57eba90101b5b2aef28)), closes [#8353](https://github.com/vuejs/core/issues/8353)
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
## [3.3.3](https://github.com/vuejs/core/compare/v3.3.2...v3.3.3) (2023-05-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* avoid regex s flag for old browsers ([91f1c62](https://github.com/vuejs/core/commit/91f1c62e6384a8b09f90e7e43b8d347901e529a0)), closes [#8316](https://github.com/vuejs/core/issues/8316)
|
||||
* **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)
|
||||
* **compiler-sfc:** don't hoist regexp literial ([#8300](https://github.com/vuejs/core/issues/8300)) ([8ec73a3](https://github.com/vuejs/core/commit/8ec73a3aea7a52e9479f107ae5737761166ddae6))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
## [3.3.2](https://github.com/vuejs/core/compare/v3.3.1...v3.3.2) (2023-05-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
## [3.3.1](https://github.com/vuejs/core/compare/v3.3.0...v3.3.1) (2023-05-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **suspense:** handle nested sync suspense for hydration ([a3f5485](https://github.com/vuejs/core/commit/a3f54857858c8ca0e6b9f12618d151ab255fb040))
|
||||
|
||||
|
||||
|
||||
# [3.3.0 Rurouni Kenshin](https://github.com/vuejs/core/compare/v3.3.0-beta.5...v3.3.0) (2023-05-11)
|
||||
|
||||
- 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).
|
||||
|
||||
- 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.
|
||||
|
||||
## Features
|
||||
|
||||
* **sfc:** support imported types in SFC macros ([#8083](https://github.com/vuejs/core/pull/8083))
|
||||
* **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))
|
||||
* **sfc:** support more ergnomic defineEmits type syntax ([#7992](https://github.com/vuejs/core/issues/7992)) ([8876dcc](https://github.com/vuejs/core/commit/8876dccf42a7f05375d97cb18c1afdfd0fc51c94))
|
||||
* **sfc:** introduce `defineModel` macro and `useModel` helper ([#8018](https://github.com/vuejs/core/issues/8018)) ([14f3d74](https://github.com/vuejs/core/commit/14f3d747a34d45415b0036b274517d70a27ec0d3))
|
||||
* **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))
|
||||
* **compiler-sfc:** add defineOptions macro ([#5738](https://github.com/vuejs/core/issues/5738)) ([bcf5841](https://github.com/vuejs/core/commit/bcf5841ddecc64d0bdbd56ce1463eb8ebf01bb9d))
|
||||
* **types/jsx:** support jsxImportSource, avoid global JSX conflict ([#7958](https://github.com/vuejs/core/issues/7958)) ([d0b7ef3](https://github.com/vuejs/core/commit/d0b7ef3b61d5f83e35e5854b3c2c874e23463102))
|
||||
* **dx:** improve readability of displayed types for props ([4c9bfd2](https://github.com/vuejs/core/commit/4c9bfd2b999ce472f7481aae4f9dc5bb9f76628e))
|
||||
* **app:** app.runWithContext() ([#7451](https://github.com/vuejs/core/issues/7451)) ([869f3fb](https://github.com/vuejs/core/commit/869f3fb93e61400be4fd925e0850c2b1564749e2))
|
||||
* hasInjectionContext() for libraries ([#8111](https://github.com/vuejs/core/issues/8111)) ([5510ce3](https://github.com/vuejs/core/commit/5510ce385abfa151c07a5253cccf4abccabdd01d))
|
||||
* 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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **types:** add slots types for built-in components ([#6033](https://github.com/vuejs/core/issues/6033)) ([3cb4dc9](https://github.com/vuejs/core/commit/3cb4dc9e5538e1c2bde9fa691b001615a848c546))
|
||||
* **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)
|
||||
* **compiler-sfc:** expose parseCache ([4576548](https://github.com/vuejs/core/commit/45765488d498d94f8760c9e82f1177070057b17c)), closes [#8202](https://github.com/vuejs/core/issues/8202)
|
||||
|
||||
## Deprecations
|
||||
|
||||
* **deprecation:** deprecate [@vnode](https://github.com/vnode) hooks in favor of vue: prefix ([5f0394a](https://github.com/vuejs/core/commit/5f0394a5ab88c82c74e240161499721f63d5462e))
|
||||
* **deprecation:** deprecate v-is directive ([bbd8301](https://github.com/vuejs/core/commit/bbd8301a1344b02de635ea16d4822db1c343bd12))
|
||||
* **deprecation:** unwrap injected refs in Options API by default, deprecate app.config.unwrapInjectedRefs ([526fa3b](https://github.com/vuejs/core/commit/526fa3b2ccf038375e76f8af2f1ddf79a7388878))
|
||||
|
||||
# [3.3.0-beta.5](https://github.com/vuejs/core/compare/v3.3.0-beta.4...v3.3.0-beta.5) (2023-05-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **build:** retain defineComponent() treeshakability in Rollup ([c2172f3](https://github.com/vuejs/core/commit/c2172f3a0ebbd7153e209dd8df6d9724bc524d9a)), closes [#8236](https://github.com/vuejs/core/issues/8236)
|
||||
* **compiler-sfc:** enable props destructure when reactivity transform option is enabled ([862edfd](https://github.com/vuejs/core/commit/862edfd91a2c2f6b75f943cb1a9682c4be5d7fa8))
|
||||
* **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)
|
||||
* **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))
|
||||
* **runtime-core:** ensure defineComponent name in extraOptions takes higher priority ([b2be75b](https://github.com/vuejs/core/commit/b2be75bad4ba70da1da6930eb914e51ce2c630b2))
|
||||
* **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)
|
||||
* **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)
|
||||
* **types:** remove short syntax support in defineSlots() ([1279b17](https://github.com/vuejs/core/commit/1279b1730079f77692a0817d51bbba57eb2b871b))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-beta.4](https://github.com/vuejs/core/compare/v3.3.0-beta.3...v3.3.0-beta.4) (2023-05-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **types:** retain compatibility for provide() usage with explicit type parameter ([038cd83](https://github.com/vuejs/core/commit/038cd830d5b34b47d7e7e1c61f0973d27cd8b915))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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)
|
||||
* **types:** add slots types for built-in components ([#6033](https://github.com/vuejs/core/issues/6033)) ([3cb4dc9](https://github.com/vuejs/core/commit/3cb4dc9e5538e1c2bde9fa691b001615a848c546))
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
# [3.3.0-beta.3](https://github.com/vuejs/core/compare/v3.3.0-beta.2...v3.3.0-beta.3) (2023-05-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-core:** handle slot argument parsing edge case ([b434d12](https://github.com/vuejs/core/commit/b434d12bf6cbd49a7c99b1646d9517d8393ea49f))
|
||||
* **hmr:** keep slots proxy mutable for hmr ([c117d9c](https://github.com/vuejs/core/commit/c117d9c257820481b85304db26ce5c77af5d050c)), closes [#8188](https://github.com/vuejs/core/issues/8188)
|
||||
* **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)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler-sfc:** expose parseCache ([4576548](https://github.com/vuejs/core/commit/45765488d498d94f8760c9e82f1177070057b17c)), closes [#8202](https://github.com/vuejs/core/issues/8202)
|
||||
|
||||
|
||||
|
||||
# [3.3.0-beta.2](https://github.com/vuejs/core/compare/v3.3.0-beta.1...v3.3.0-beta.2) (2023-04-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-sfc:** avoid all hard errors when inferring runtime type ([2d9f6f9](https://github.com/vuejs/core/commit/2d9f6f926453c46f542789927bcd30d15da9c24b))
|
||||
* **compiler-sfc:** normalize windows paths when resolving types ([#8136](https://github.com/vuejs/core/issues/8136)) ([29da504](https://github.com/vuejs/core/commit/29da50468770fcee16ba5d5bec7166dd5bc120ee))
|
||||
* **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)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-sfc:** infer ref binding type for more built-in methods ([a370e80](https://github.com/vuejs/core/commit/a370e8006a70ea49a7d04c8c1a42d0947eba5dea))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-beta.1](https://github.com/vuejs/core/compare/v3.3.0-alpha.13...v3.3.0-beta.1) (2023-04-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 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)
|
||||
* **compiler-sfc:** improve utility type Partial and Required ([#8103](https://github.com/vuejs/core/issues/8103)) ([1d1d728](https://github.com/vuejs/core/commit/1d1d72894995fde14bd09e2990462c19d5176bf9))
|
||||
* **deprecation:** deprecate [@vnode](https://github.com/vnode) hooks in favor of vue: prefix ([5f0394a](https://github.com/vuejs/core/commit/5f0394a5ab88c82c74e240161499721f63d5462e))
|
||||
* **deprecation:** deprecate v-is directive ([bbd8301](https://github.com/vuejs/core/commit/bbd8301a1344b02de635ea16d4822db1c343bd12))
|
||||
* **deprecation:** unwrap injected refs in Options API by default, deprecate app.config.unwrapInjectedRefs ([526fa3b](https://github.com/vuejs/core/commit/526fa3b2ccf038375e76f8af2f1ddf79a7388878))
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.13](https://github.com/vuejs/core/compare/v3.3.0-alpha.12...v3.3.0-alpha.13) (2023-04-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **compiler-sfc:** normalize filename when invalidating cache ([9b5a34b](https://github.com/vuejs/core/commit/9b5a34bf8c0d1b4c6ec3cf1434076b7e25065f84))
|
||||
* **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)
|
||||
* **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)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler-sfc:** support dynamic imports when resolving types ([4496456](https://github.com/vuejs/core/commit/4496456d7d9947560ef1e35ccb176b97a27bd8f4))
|
||||
* **compiler-sfc:** support export * when resolving types ([7c3ca3c](https://github.com/vuejs/core/commit/7c3ca3cc3e122fe273e80a950c57d492a7f0bf4a))
|
||||
* **compiler-sfc:** support ExtractPropTypes when resolving types ([50c0bbe](https://github.com/vuejs/core/commit/50c0bbe5221dbc1dc353d4960e69ec7c8ba12905)), closes [#8104](https://github.com/vuejs/core/issues/8104)
|
||||
* hasInjectionContext() for libraries ([#8111](https://github.com/vuejs/core/issues/8111)) ([5510ce3](https://github.com/vuejs/core/commit/5510ce385abfa151c07a5253cccf4abccabdd01d))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.12](https://github.com/vuejs/core/compare/v3.3.0-alpha.11...v3.3.0-alpha.12) (2023-04-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** fix expression codegen for literal const bindings in non-inline mode ([0f77a2b](https://github.com/vuejs/core/commit/0f77a2b1d1047d66ccdfda70382d1a223886130c))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.11](https://github.com/vuejs/core/compare/v3.3.0-alpha.10...v3.3.0-alpha.11) (2023-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-sfc:** normalize windows paths when resolving types ([271df09](https://github.com/vuejs/core/commit/271df09470c61d073185ba6cf3cf50358713c500))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.10](https://github.com/vuejs/core/compare/v3.3.0-alpha.9...v3.3.0-alpha.10) (2023-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **hmr:** invalidate cached props/emits options on hmr ([4b5b384](https://github.com/vuejs/core/commit/4b5b384485cf8f6124f6738b89e3d047358f3a11))
|
||||
* **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)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler-sfc:** expose type import deps on compiled script block ([8d8ddd6](https://github.com/vuejs/core/commit/8d8ddd686c832b2ea29b87ef47666b13c4ad5d4c))
|
||||
* **compiler-sfc:** expose type resolve APIs ([f22e32e](https://github.com/vuejs/core/commit/f22e32e365bf6292cb606cb7289609e82da8b790))
|
||||
* **compiler-sfc:** mark props destructure as experimental and require explicit opt-in ([6b13e04](https://github.com/vuejs/core/commit/6b13e04b4c83fcdbb180dc1d59f536a1309c2960))
|
||||
* **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)
|
||||
* **compiler-sfc:** support limited built-in utility types in macros ([1cfab4c](https://github.com/vuejs/core/commit/1cfab4c695b0c28f549f8c97faee5099581792a7))
|
||||
* **compiler-sfc:** support mapped types, string types & template type in macros ([fb8ecc8](https://github.com/vuejs/core/commit/fb8ecc803e58bfef0971346c63fefc529812daa7))
|
||||
* **compiler-sfc:** support namespace members type in macros ([5ff40bb](https://github.com/vuejs/core/commit/5ff40bb0dc2918b7db15fe9f49db2a135a925572))
|
||||
* **compiler-sfc:** support relative imported types in macros ([8aa4ea8](https://github.com/vuejs/core/commit/8aa4ea81d6e4d3110aa1619cca594543da4c9b63))
|
||||
* **compiler-sfc:** support resolving type imports from modules ([3982bef](https://github.com/vuejs/core/commit/3982bef533b451d1b59fa243560184a13fe8c18c))
|
||||
* **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)
|
||||
* **compiler-sfc:** support string indexed type in macros ([3f779dd](https://github.com/vuejs/core/commit/3f779ddbf85054c8915fa4537f8a79baab392d5c))
|
||||
* **compiler-sfc:** support string/number indexed types in macros ([760755f](https://github.com/vuejs/core/commit/760755f4f83680bee13ad546cdab2e48ade38dff))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler:** use source-map-js ([19e17a9](https://github.com/vuejs/core/commit/19e17a951c3387cbd6a1597e6cd9048a4aad4528))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.9](https://github.com/vuejs/core/compare/v3.3.0-alpha.8...v3.3.0-alpha.9) (2023-04-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **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))
|
||||
* **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))
|
||||
* **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)
|
||||
* **types:** improve defineProps return type with generic arguments ([91a931a](https://github.com/vuejs/core/commit/91a931ae8707b8d43f10216e1ce8e18b12158f99))
|
||||
* **types:** more public type argument order fix ([af563bf](https://github.com/vuejs/core/commit/af563bf428200367b6f5bb7944f690c85d810202))
|
||||
* **types:** retain type parameters order for public types ([bdf557f](https://github.com/vuejs/core/commit/bdf557f6f233c039fff8007b1b16aec00c4e68aa))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **app:** app.runWithContext() ([#7451](https://github.com/vuejs/core/issues/7451)) ([869f3fb](https://github.com/vuejs/core/commit/869f3fb93e61400be4fd925e0850c2b1564749e2))
|
||||
* **sfc:** introduce `defineModel` macro and `useModel` helper ([#8018](https://github.com/vuejs/core/issues/8018)) ([14f3d74](https://github.com/vuejs/core/commit/14f3d747a34d45415b0036b274517d70a27ec0d3))
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "chore: remove unused args passed to ssrRender" ([b117b88](https://github.com/vuejs/core/commit/b117b8844881a732a021432066230ff2215049ea))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.8](https://github.com/vuejs/core/compare/v3.3.0-alpha.7...v3.3.0-alpha.8) (2023-04-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.7](https://github.com/vuejs/core/compare/v3.3.0-alpha.6...v3.3.0-alpha.7) (2023-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **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)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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))
|
||||
* **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)
|
||||
* **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))
|
||||
* **sfc:** revert withDefaults() deprecation ([4af5d1b](https://github.com/vuejs/core/commit/4af5d1b0754035058436f9e4e5c12aedef199177))
|
||||
* **sfc:** support more ergnomic defineEmits type syntax ([#7992](https://github.com/vuejs/core/issues/7992)) ([8876dcc](https://github.com/vuejs/core/commit/8876dccf42a7f05375d97cb18c1afdfd0fc51c94))
|
||||
* **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))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.6](https://github.com/vuejs/core/compare/v3.3.0-alpha.5...v3.3.0-alpha.6) (2023-03-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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)
|
||||
* **compiler-core:** fix codegen for literal const in non-inline mode ([6bda4b6](https://github.com/vuejs/core/commit/6bda4b66886240b28993c88b7ecd4640a199be65))
|
||||
* **compiler-sfc:** allow `<script>` with lang='js' ([#7398](https://github.com/vuejs/core/issues/7398)) ([9f5e20c](https://github.com/vuejs/core/commit/9f5e20ccff235946159f0e50519f5be09bc89d5b))
|
||||
* **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)
|
||||
* **compiler-sfc:** disallow `expose` property in `defineOptions` ([#7967](https://github.com/vuejs/core/issues/7967)) ([93f7729](https://github.com/vuejs/core/commit/93f77292c9f2c4dcc83aae6b5943a8b1d7443092))
|
||||
* **compiler-sfc:** fix defineExpose() codegen regression from [#7949](https://github.com/vuejs/core/issues/7949) ([a94072d](https://github.com/vuejs/core/commit/a94072dd2ca1aca4ce1fbe5da51ca2a9a07a4637))
|
||||
* **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)
|
||||
* **compiler-sfc:** fix function default value handling w/ props destructure ([e10a89e](https://github.com/vuejs/core/commit/e10a89e608d3486c0c9a0457ee7c56d208e0aa91))
|
||||
* **compiler-sfc:** handle more TS built-in utilities in defineProps inference ([4355d24](https://github.com/vuejs/core/commit/4355d2492dccdb175b18d083e20f3ec39a52801f))
|
||||
* **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))
|
||||
* **compiler-sfc:** infer object type for empty type literal ([1a04fba](https://github.com/vuejs/core/commit/1a04fba10b6462303c65f1095da86ce05c14f1f4))
|
||||
* **compiler-sfc:** infer runtime type in defineProps ([#7972](https://github.com/vuejs/core/issues/7972)) ([ba4cec3](https://github.com/vuejs/core/commit/ba4cec31b91da60555892c381b00c2fa5b3e0e39))
|
||||
* **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)
|
||||
* **compiler-sfc:** infer TSIntersectionType in defineProps ([#7394](https://github.com/vuejs/core/issues/7394)) ([151a8ad](https://github.com/vuejs/core/commit/151a8ad6b9288784c3b2514820a112b93ecf2dca))
|
||||
* **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)
|
||||
* **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)
|
||||
* **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)
|
||||
* **compiler-sfc:** unwrap TS node for defineProps ([#7340](https://github.com/vuejs/core/issues/7340)) ([1b69d5f](https://github.com/vuejs/core/commit/1b69d5f2f49ee60af4b10137c7833a76420dbba1))
|
||||
* **compiler-sfc:** use prependLeft to handle CSSVars ([#7760](https://github.com/vuejs/core/issues/7760)) ([139104b](https://github.com/vuejs/core/commit/139104ba2695eecae672db98f978de78e17ab7e1))
|
||||
* **jsx-runtime:** fix automatic runtime implementation ([#7959](https://github.com/vuejs/core/issues/7959)) ([5838950](https://github.com/vuejs/core/commit/5838950ecf7e4e17dd5a23acd621077390666b76))
|
||||
* **jsx-runtime:** handle keys ([#7976](https://github.com/vuejs/core/issues/7976)) ([ff60b93](https://github.com/vuejs/core/commit/ff60b933ae4e02422393664ee7818cffadf9b58b))
|
||||
* **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))
|
||||
* **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))
|
||||
* **types/jsx:** remove $slots children override ([28e30c8](https://github.com/vuejs/core/commit/28e30c819df5e4fc301c98f7be938fa13e8be3bc))
|
||||
* **types:** revert jsx global removal (to be removed in 3.4) ([e224922](https://github.com/vuejs/core/commit/e224922e972e78b4fb6cbd129d685c2317018ad1))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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))
|
||||
* **compiler-sfc:** add defineOptions macro ([#5738](https://github.com/vuejs/core/issues/5738)) ([bcf5841](https://github.com/vuejs/core/commit/bcf5841ddecc64d0bdbd56ce1463eb8ebf01bb9d))
|
||||
* **compiler-sfc:** enable reactive props destructure by default ([#7986](https://github.com/vuejs/core/issues/7986)) ([ba9c2ae](https://github.com/vuejs/core/commit/ba9c2ae247fcc3960b238a04cb635158daa82004))
|
||||
* **compiler-sfc:** improve runtime props inference for enum ([eded947](https://github.com/vuejs/core/commit/eded94712e37856f258dc8c85f98a26fa41ae05f))
|
||||
* **compiler-sfc:** support generating variable instead of default export in compileScript ([71635be](https://github.com/vuejs/core/commit/71635be68d25887f91d624bb7f78281a851bc0cb))
|
||||
* **compiler-sfc:** support module string names syntax ([#7428](https://github.com/vuejs/core/issues/7428)) ([0002567](https://github.com/vuejs/core/commit/000256772816d54976e462330a7be342c49c7304))
|
||||
* **complier-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)
|
||||
* **runtime-core:** add skipCheck for prop ([#7548](https://github.com/vuejs/core/issues/7548)) ([63ad77f](https://github.com/vuejs/core/commit/63ad77f6f65751780aa52f817387165b4773cfe4))
|
||||
* **sfc:** deprecate reactivity transform ([efb54e7](https://github.com/vuejs/core/commit/efb54e7315e93f4be7004d1c0a4de8c523dab334))
|
||||
* **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)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **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.
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.5](https://github.com/vuejs/core/compare/v3.3.0-alpha.4...v3.3.0-alpha.5) (2023-03-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **runtime-core:** support `getCurrentInstance` across mutiple builds of Vue ([8d2d5bf](https://github.com/vuejs/core/commit/8d2d5bf48a24dab44e5b03cb8fa0c5faa4b696e3))
|
||||
* **types:** ensure defineProps with generics return correct types ([c288c7b](https://github.com/vuejs/core/commit/c288c7b0bd6077d690f42153c3fc49a45454a66a))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **dx:** improve readability of displayed types for props ([4c9bfd2](https://github.com/vuejs/core/commit/4c9bfd2b999ce472f7481aae4f9dc5bb9f76628e))
|
||||
* **types/jsx:** support jsxImportSource, avoid global JSX conflict ([#7958](https://github.com/vuejs/core/issues/7958)) ([d0b7ef3](https://github.com/vuejs/core/commit/d0b7ef3b61d5f83e35e5854b3c2c874e23463102))
|
||||
|
||||
### Note on JSX Types Change
|
||||
|
||||
* 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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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).
|
||||
|
||||
# [3.3.0-alpha.4](https://github.com/vuejs/core/compare/v3.3.0-alpha.3...v3.3.0-alpha.4) (2023-02-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **build:** fix const enum w/ number values ([92bb189](https://github.com/vuejs/core/commit/92bb189ca7ecae221ebf5411da87c715780d2de3))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.3](https://github.com/vuejs/core/compare/v3.3.0-alpha.2...v3.3.0-alpha.3) (2023-02-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **build:** avoid const enum conflicts ([d1181ad](https://github.com/vuejs/core/commit/d1181ad692861c140e687372efbc67a1d65d642a))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.2](https://github.com/vuejs/core/compare/v3.3.0-alpha.1...v3.3.0-alpha.2) (2023-02-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **build:** fix dev flag replacement in esm-bundler builds ([5851eaa](https://github.com/vuejs/core/commit/5851eaa9339364d41860a277a99f2352de2a3834))
|
||||
|
||||
|
||||
|
||||
# [3.3.0-alpha.1](https://github.com/vuejs/core/compare/v3.2.47...v3.3.0-alpha.1) (2023-02-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **build:** ensure BaseTransition functions can be tree-shaken ([3a6f5eb](https://github.com/vuejs/core/commit/3a6f5eb0f7d60dc87d17a69c66e88ae5688b11a5))
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,181 @@
|
|||
import importX from 'eslint-plugin-import-x'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import vitest from 'eslint-plugin-vitest'
|
||||
import { builtinModules } from 'node:module'
|
||||
|
||||
const DOMGlobals = ['window', 'document']
|
||||
const NodeGlobals = ['module', 'require']
|
||||
|
||||
const banConstEnum = {
|
||||
selector: 'TSEnumDeclaration[const=true]',
|
||||
message:
|
||||
'Please use non-const enums. This project automatically inlines enums.',
|
||||
}
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts', '**/*.tsx'],
|
||||
extends: [tseslint.configs.base],
|
||||
plugins: {
|
||||
'import-x': importX,
|
||||
},
|
||||
rules: {
|
||||
'no-debugger': 'error',
|
||||
'no-console': ['error', { allow: ['warn', 'error', 'info'] }],
|
||||
// most of the codebase are expected to be env agnostic
|
||||
'no-restricted-globals': ['error', ...DOMGlobals, ...NodeGlobals],
|
||||
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
banConstEnum,
|
||||
{
|
||||
selector: 'ObjectPattern > RestElement',
|
||||
message:
|
||||
'Our output target is ES2016, and object rest spread results in ' +
|
||||
'verbose helpers and should be avoided.',
|
||||
},
|
||||
{
|
||||
selector: 'ObjectExpression > SpreadElement',
|
||||
message:
|
||||
'esbuild transpiles object spread into very verbose inline helpers.\n' +
|
||||
'Please use the `extend` helper from @vue/shared instead.',
|
||||
},
|
||||
{
|
||||
selector: 'AwaitExpression',
|
||||
message:
|
||||
'Our output target is ES2016, so async/await syntax should be avoided.',
|
||||
},
|
||||
{
|
||||
selector: 'ChainExpression',
|
||||
message:
|
||||
'Our output target is ES2016, and optional chaining results in ' +
|
||||
'verbose helpers and should be avoided.',
|
||||
},
|
||||
],
|
||||
'sort-imports': ['error', { ignoreDeclarationSort: true }],
|
||||
|
||||
'import-x/no-nodejs-modules': [
|
||||
'error',
|
||||
{ allow: builtinModules.map(mod => `node:${mod}`) },
|
||||
],
|
||||
// This rule enforces the preference for using '@ts-expect-error' comments in TypeScript
|
||||
// code to indicate intentional type errors, improving code clarity and maintainability.
|
||||
'@typescript-eslint/prefer-ts-expect-error': 'error',
|
||||
// Enforce the use of 'import type' for importing types
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'error',
|
||||
{
|
||||
fixStyle: 'inline-type-imports',
|
||||
disallowTypeAnnotations: false,
|
||||
},
|
||||
],
|
||||
// Enforce the use of top-level import type qualifier when an import only has specifiers with inline type qualifiers
|
||||
'@typescript-eslint/no-import-type-side-effects': 'error',
|
||||
},
|
||||
},
|
||||
|
||||
// tests, no restrictions (runs in Node / Vitest with jsdom)
|
||||
{
|
||||
files: [
|
||||
'**/__tests__/**',
|
||||
'packages-private/dts-test/**',
|
||||
'packages-private/dts-build-test/**',
|
||||
],
|
||||
plugins: { vitest },
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...vitest.environments.env.globals,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
'no-restricted-globals': 'off',
|
||||
'no-restricted-syntax': 'off',
|
||||
'vitest/no-disabled-tests': 'error',
|
||||
'vitest/no-focused-tests': 'error',
|
||||
},
|
||||
},
|
||||
|
||||
// shared, may be used in any env
|
||||
{
|
||||
files: ['packages/shared/**', 'eslint.config.js'],
|
||||
rules: {
|
||||
'no-restricted-globals': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// Packages targeting DOM
|
||||
{
|
||||
files: ['packages/{vue,vue-compat,runtime-dom}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
},
|
||||
},
|
||||
|
||||
// Packages targeting Node
|
||||
{
|
||||
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...DOMGlobals],
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
},
|
||||
},
|
||||
|
||||
// Private package, browser only + no syntax restrictions
|
||||
{
|
||||
files: [
|
||||
'packages-private/template-explorer/**',
|
||||
'packages-private/sfc-playground/**',
|
||||
],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// JavaScript files
|
||||
{
|
||||
files: ['*.js'],
|
||||
rules: {
|
||||
// We only do `no-unused-vars` checks for js files, TS files are checked by TypeScript itself.
|
||||
'no-unused-vars': ['error', { vars: 'all', args: 'none' }],
|
||||
},
|
||||
},
|
||||
|
||||
// Node scripts
|
||||
{
|
||||
files: [
|
||||
'eslint.config.js',
|
||||
'rollup*.config.js',
|
||||
'scripts/**',
|
||||
'./*.{js,ts}',
|
||||
'packages/*/*.js',
|
||||
'packages/vue/*/*.js',
|
||||
],
|
||||
rules: {
|
||||
'no-restricted-globals': 'off',
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// Import nodejs modules in compiler-sfc
|
||||
{
|
||||
files: ['packages/compiler-sfc/src/**'],
|
||||
rules: {
|
||||
'import-x/no-nodejs-modules': ['error', { allow: builtinModules }],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
ignores: [
|
||||
'**/dist/',
|
||||
'**/temp/',
|
||||
'**/coverage/',
|
||||
'.idea/',
|
||||
'explorations/',
|
||||
'dts-build/packages',
|
||||
],
|
||||
},
|
||||
)
|
|
@ -1,51 +0,0 @@
|
|||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
setupFilesAfterEnv: ['./scripts/setupJestEnv.ts'],
|
||||
globals: {
|
||||
__DEV__: true,
|
||||
__TEST__: true,
|
||||
__VERSION__: require('./package.json').version,
|
||||
__BROWSER__: false,
|
||||
__GLOBAL__: false,
|
||||
__ESM_BUNDLER__: true,
|
||||
__ESM_BROWSER__: false,
|
||||
__NODE_JS__: true,
|
||||
__FEATURE_OPTIONS_API__: true,
|
||||
__FEATURE_SUSPENSE__: true,
|
||||
__FEATURE_PROD_DEVTOOLS__: false,
|
||||
__COMPAT__: true
|
||||
},
|
||||
coverageDirectory: 'coverage',
|
||||
coverageReporters: ['html', 'lcov', 'text'],
|
||||
collectCoverageFrom: [
|
||||
'packages/*/src/**/*.ts',
|
||||
'!packages/runtime-test/src/utils/**',
|
||||
'!packages/template-explorer/**',
|
||||
'!packages/sfc-playground/**',
|
||||
'!packages/size-check/**',
|
||||
'!packages/runtime-core/src/profiling.ts',
|
||||
'!packages/runtime-core/src/customFormatter.ts',
|
||||
// DOM transitions are tested via e2e so no coverage is collected
|
||||
'!packages/runtime-dom/src/components/Transition*',
|
||||
// only called in browsers
|
||||
'!packages/vue/src/devCheck.ts',
|
||||
// only used as a build entry
|
||||
'!packages/vue/src/runtime.ts',
|
||||
// mostly just entries
|
||||
'!packages/vue-compat/**'
|
||||
],
|
||||
watchPathIgnorePatterns: ['/node_modules/', '/dist/', '/.git/'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
|
||||
moduleNameMapper: {
|
||||
'@vue/compat': '<rootDir>/packages/vue-compat/src',
|
||||
'^@vue/(.*?)$': '<rootDir>/packages/$1/src',
|
||||
vue: '<rootDir>/packages/vue/src'
|
||||
},
|
||||
rootDir: __dirname,
|
||||
testMatch: ['<rootDir>/packages/**/__tests__/**/*spec.[jt]s?(x)'],
|
||||
testPathIgnorePatterns: process.env.SKIP_E2E
|
||||
? // ignore example tests on netlify builds since they don't contribute
|
||||
// to coverage and can cause netlify builds to fail
|
||||
['/node_modules/', '/examples/__tests__']
|
||||
: ['/node_modules/']
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
[build.environment]
|
||||
NODE_VERSION = "18"
|
||||
NPM_FLAGS = "--version" # prevent Netlify npm install
|
163
package.json
163
package.json
|
@ -1,83 +1,124 @@
|
|||
{
|
||||
"private": true,
|
||||
"version": "3.1.1",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "3.5.3",
|
||||
"packageManager": "pnpm@9.9.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "node scripts/dev.js",
|
||||
"build": "node scripts/build.js",
|
||||
"size": "node scripts/build.js vue runtime-dom size-check -p -f global",
|
||||
"lint": "eslint --ext .ts packages/*/src/**",
|
||||
"format": "prettier --write --parser typescript \"packages/**/*.ts?(x)\"",
|
||||
"test": "node scripts/build.js vue -f global -d && jest --runInBand",
|
||||
"test-dts": "node scripts/build.js shared reactivity runtime-core runtime-dom -dt -f esm-bundler && yarn test-dts-only",
|
||||
"test-dts-only": "tsc -p ./test-dts/tsconfig.json && tsc -p ./test-dts/tsconfig.build.json",
|
||||
"build-dts": "tsc -p tsconfig.build-browser.json && tsc -p tsconfig.build-node.json && rollup -c rollup.dts.config.js",
|
||||
"clean": "rimraf --glob packages/*/dist temp .eslintcache",
|
||||
"size": "run-s \"size-*\" && tsx scripts/usage-size.ts",
|
||||
"size-global": "node scripts/build.js vue runtime-dom -f global -p --size",
|
||||
"size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime",
|
||||
"size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
|
||||
"check": "tsc --incremental --noEmit",
|
||||
"lint": "eslint --cache .",
|
||||
"format": "prettier --write --cache .",
|
||||
"format-check": "prettier --check --cache .",
|
||||
"test": "vitest",
|
||||
"test-unit": "vitest -c vitest.unit.config.ts",
|
||||
"test-e2e": "node scripts/build.js vue -f global -d && vitest -c vitest.e2e.config.ts",
|
||||
"test-dts": "run-s build-dts test-dts-only",
|
||||
"test-dts-only": "tsc -p packages-private/dts-built-test/tsconfig.json && tsc -p ./packages-private/dts-test/tsconfig.test.json",
|
||||
"test-coverage": "vitest run -c vitest.unit.config.ts --coverage",
|
||||
"test-bench": "vitest bench",
|
||||
"release": "node scripts/release.js",
|
||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
|
||||
"dev-compiler": "npm-run-all --parallel \"dev template-explorer\" serve",
|
||||
"dev-esm": "node scripts/dev.js -if esm-bundler-runtime",
|
||||
"dev-compiler": "run-p \"dev template-explorer\" serve",
|
||||
"dev-sfc": "run-s dev-sfc-prepare dev-sfc-run",
|
||||
"dev-sfc-prepare": "node scripts/pre-dev-sfc.js || npm run build-all-cjs",
|
||||
"dev-sfc-serve": "vite packages-private/sfc-playground --host",
|
||||
"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",
|
||||
"serve": "serve",
|
||||
"open": "open http://localhost:5000/packages/template-explorer/local.html",
|
||||
"preinstall": "node ./scripts/checkYarn.js",
|
||||
"prebuild-sfc-playground": "node scripts/build.js compiler shared -af cjs && 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 && node scripts/build.js compiler-sfc -f esm-browser",
|
||||
"build-sfc-playground": "cd packages/sfc-playground && vite build"
|
||||
"open": "open http://localhost:3000/packages-private/template-explorer/local.html",
|
||||
"build-sfc-playground": "run-s build-all-cjs build-runtime-esm build-browser-esm build-ssr-esm build-sfc-playground-self",
|
||||
"build-all-cjs": "node scripts/build.js vue runtime compiler reactivity shared -af cjs",
|
||||
"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",
|
||||
"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",
|
||||
"build-ssr-esm": "node scripts/build.js compiler-sfc server-renderer -f esm-browser",
|
||||
"build-sfc-playground-self": "cd packages-private/sfc-playground && npm run build",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"postinstall": "simple-git-hooks"
|
||||
},
|
||||
"types": "test-dts/index.d.ts",
|
||||
"tsd": {
|
||||
"directory": "test-dts"
|
||||
},
|
||||
"gitHooks": {
|
||||
"pre-commit": "lint-staged",
|
||||
"commit-msg": "node scripts/verifyCommit.js"
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "pnpm lint-staged && pnpm check",
|
||||
"commit-msg": "node scripts/verify-commit.js"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"*.{js,json}": [
|
||||
"prettier --write"
|
||||
],
|
||||
"*.ts?(x)": [
|
||||
"eslint",
|
||||
"eslint --fix",
|
||||
"prettier --parser=typescript --write"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
"node": ">=18.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/types": "^7.12.0",
|
||||
"@microsoft/api-extractor": "^7.15.1",
|
||||
"@rollup/plugin-commonjs": "^18.0.0",
|
||||
"@rollup/plugin-json": "^4.0.0",
|
||||
"@rollup/plugin-node-resolve": "^11.2.1",
|
||||
"@rollup/plugin-replace": "^2.3.4",
|
||||
"@types/hash-sum": "^1.0.0",
|
||||
"@types/jest": "^26.0.16",
|
||||
"@types/node": "^14.10.1",
|
||||
"@types/puppeteer": "^2.0.0",
|
||||
"@typescript-eslint/parser": "^4.1.1",
|
||||
"brotli": "^1.3.2",
|
||||
"chalk": "^4.1.0",
|
||||
"conventional-changelog-cli": "^2.0.31",
|
||||
"csstype": "^3.0.3",
|
||||
"enquirer": "^2.3.2",
|
||||
"eslint": "^7.7.0",
|
||||
"execa": "^4.0.2",
|
||||
"fs-extra": "^9.0.1",
|
||||
"jest": "^26.0.1",
|
||||
"lint-staged": "^10.2.10",
|
||||
"minimist": "^1.2.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "~1.14.0",
|
||||
"puppeteer": "^2.0.0",
|
||||
"rollup": "~2.38.5",
|
||||
"rollup-plugin-node-builtins": "^2.1.2",
|
||||
"rollup-plugin-node-globals": "^1.4.0",
|
||||
"rollup-plugin-polyfill-node": "^0.6.2",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"rollup-plugin-typescript2": "^0.27.2",
|
||||
"semver": "^7.3.2",
|
||||
"serve": "^11.3.0",
|
||||
"ts-jest": "^26.2.0",
|
||||
"typescript": "^4.2.2",
|
||||
"yorkie": "^2.0.0"
|
||||
"@babel/parser": "catalog:",
|
||||
"@babel/types": "catalog:",
|
||||
"@rollup/plugin-alias": "^5.1.0",
|
||||
"@rollup/plugin-commonjs": "^26.0.1",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-replace": "5.0.4",
|
||||
"@swc/core": "^1.7.23",
|
||||
"@types/hash-sum": "^1.0.2",
|
||||
"@types/node": "^20.16.3",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/serve-handler": "^6.1.4",
|
||||
"@vitest/coverage-v8": "^2.0.5",
|
||||
"@vue/consolidate": "1.0.0",
|
||||
"conventional-changelog-cli": "^5.0.0",
|
||||
"enquirer": "^2.4.1",
|
||||
"esbuild": "^0.23.1",
|
||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||
"eslint": "^9.9.1",
|
||||
"eslint-plugin-import-x": "^3.1.0",
|
||||
"eslint-plugin-vitest": "^0.5.4",
|
||||
"estree-walker": "catalog:",
|
||||
"jsdom": "^25.0.0",
|
||||
"lint-staged": "^15.2.10",
|
||||
"lodash": "^4.17.21",
|
||||
"magic-string": "^0.30.11",
|
||||
"markdown-table": "^3.0.3",
|
||||
"marked": "13.0.3",
|
||||
"npm-run-all2": "^6.2.2",
|
||||
"picocolors": "^1.1.0",
|
||||
"prettier": "^3.3.3",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
"pug": "^3.0.3",
|
||||
"puppeteer": "~23.3.0",
|
||||
"rimraf": "^6.0.1",
|
||||
"rollup": "^4.21.2",
|
||||
"rollup-plugin-dts": "^6.1.1",
|
||||
"rollup-plugin-esbuild": "^6.1.1",
|
||||
"rollup-plugin-polyfill-node": "^0.13.0",
|
||||
"semver": "^7.6.3",
|
||||
"serve": "^14.2.3",
|
||||
"serve-handler": "^6.1.5",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"todomvc-app-css": "^2.4.3",
|
||||
"tslib": "^2.7.0",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "~5.5.4",
|
||||
"typescript-eslint": "^8.4.0",
|
||||
"vite": "catalog:",
|
||||
"vitest": "^2.0.5"
|
||||
},
|
||||
"pnpm": {
|
||||
"peerDependencyRules": {
|
||||
"allowedVersions": {
|
||||
"typescript-eslint>eslint": "^9.0.0",
|
||||
"@typescript-eslint/eslint-plugin>eslint": "^9.0.0",
|
||||
"@typescript-eslint/parser>eslint": "^9.0.0",
|
||||
"@typescript-eslint/type-utils>eslint": "^9.0.0",
|
||||
"@typescript-eslint/utils>eslint": "^9.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# dts built-package test
|
||||
|
||||
This 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).
|
||||
|
||||
When 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.
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "dts-built-test",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"types": "dist/index.d.ts",
|
||||
"dependencies": {
|
||||
"@vue/shared": "workspace:*",
|
||||
"@vue/reactivity": "workspace:*",
|
||||
"vue": "workspace:*"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { defineComponent } from 'vue'
|
||||
|
||||
const _CustomPropsNotErased = defineComponent({
|
||||
props: {},
|
||||
setup() {},
|
||||
})
|
||||
|
||||
// #8376
|
||||
export const CustomPropsNotErased =
|
||||
_CustomPropsNotErased as typeof _CustomPropsNotErased & {
|
||||
foo: string
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"outDir": "dist",
|
||||
"jsx": "preserve",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"moduleResolution": "Bundler",
|
||||
"lib": ["esnext", "dom"],
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# dts-test
|
||||
|
||||
Tests TypeScript types to ensure the types remain as expected.
|
||||
|
||||
- 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.
|
||||
|
||||
- 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`.
|
|
@ -0,0 +1,14 @@
|
|||
import { createApp } from 'vue'
|
||||
import { expectType } from './utils'
|
||||
|
||||
const app = createApp({})
|
||||
|
||||
app.directive<HTMLElement, string>('custom', {
|
||||
mounted(el, binding) {
|
||||
expectType<HTMLElement>(el)
|
||||
expectType<string>(binding.value)
|
||||
|
||||
// @ts-expect-error not any
|
||||
expectType<number>(binding.value)
|
||||
},
|
||||
})
|
|
@ -0,0 +1,107 @@
|
|||
import { type App, type Plugin, createApp, defineComponent } from 'vue'
|
||||
|
||||
const app = createApp({})
|
||||
|
||||
// Plugin without types accept anything
|
||||
const PluginWithoutType: Plugin = {
|
||||
install(app: App) {},
|
||||
}
|
||||
|
||||
app.use(PluginWithoutType)
|
||||
app.use(PluginWithoutType, 2)
|
||||
app.use(PluginWithoutType, { anything: 'goes' }, true)
|
||||
|
||||
type PluginOptions = {
|
||||
option1?: string
|
||||
option2: number
|
||||
option3: boolean
|
||||
}
|
||||
|
||||
const PluginWithObjectOptions = {
|
||||
install(app: App, options: PluginOptions) {
|
||||
options.option1
|
||||
options.option2
|
||||
options.option3
|
||||
},
|
||||
}
|
||||
|
||||
for (const Plugin of [
|
||||
PluginWithObjectOptions,
|
||||
PluginWithObjectOptions.install,
|
||||
]) {
|
||||
// @ts-expect-error: no params
|
||||
app.use(Plugin)
|
||||
|
||||
// @ts-expect-error option2 and option3 (required) missing
|
||||
app.use(Plugin, {})
|
||||
// @ts-expect-error type mismatch
|
||||
app.use(Plugin, undefined)
|
||||
// valid options
|
||||
app.use(Plugin, { option2: 1, option3: true })
|
||||
app.use(Plugin, { option1: 'foo', option2: 1, option3: true })
|
||||
}
|
||||
|
||||
const PluginNoOptions = {
|
||||
install(app: App) {},
|
||||
}
|
||||
|
||||
for (const Plugin of [PluginNoOptions, PluginNoOptions.install]) {
|
||||
// no args
|
||||
app.use(Plugin)
|
||||
// @ts-expect-error unexpected plugin option
|
||||
app.use(Plugin, {})
|
||||
// @ts-expect-error only no options is valid
|
||||
app.use(Plugin, undefined)
|
||||
}
|
||||
|
||||
const PluginMultipleArgs = {
|
||||
install: (app: App, a: string, b: number) => {},
|
||||
}
|
||||
|
||||
for (const Plugin of [PluginMultipleArgs, PluginMultipleArgs.install]) {
|
||||
// @ts-expect-error: 2 arguments expected
|
||||
app.use(Plugin, 'hey')
|
||||
app.use(Plugin, 'hey', 2)
|
||||
}
|
||||
|
||||
const PluginOptionalOptions = {
|
||||
install(
|
||||
app: App,
|
||||
options: PluginOptions = { option2: 2, option3: true, option1: 'foo' },
|
||||
) {
|
||||
options.option1
|
||||
options.option2
|
||||
options.option3
|
||||
},
|
||||
}
|
||||
|
||||
for (const Plugin of [PluginOptionalOptions, PluginOptionalOptions.install]) {
|
||||
// both version are valid
|
||||
app.use(Plugin)
|
||||
app.use(Plugin, undefined)
|
||||
|
||||
// @ts-expect-error option2 and option3 (required) missing
|
||||
app.use(Plugin, {})
|
||||
// valid options
|
||||
app.use(Plugin, { option2: 1, option3: true })
|
||||
app.use(Plugin, { option1: 'foo', option2: 1, option3: true })
|
||||
}
|
||||
|
||||
// still valid but it's better to use the regular function because this one can accept an optional param
|
||||
const PluginTyped: Plugin<PluginOptions> = (app, options) => {}
|
||||
|
||||
// @ts-expect-error: needs options
|
||||
app.use(PluginTyped)
|
||||
app.use(PluginTyped, { option2: 2, option3: true })
|
||||
|
||||
// vuetify usage
|
||||
const key: string = ''
|
||||
const aliases: Record<string, any> = {}
|
||||
app.component(
|
||||
key,
|
||||
defineComponent({
|
||||
...aliases[key],
|
||||
name: key,
|
||||
aliasName: aliases[key].name,
|
||||
}),
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
import { CustomPropsNotErased } from 'dts-built-test/src/index'
|
||||
import { describe, expectType } from './utils'
|
||||
|
||||
declare module 'vue' {
|
||||
interface ComponentCustomProps {
|
||||
custom?: number
|
||||
}
|
||||
}
|
||||
|
||||
// #8376 - custom props should not be erased
|
||||
describe('Custom Props not erased', () => {
|
||||
expectType<number | undefined>(new CustomPropsNotErased().$props.custom)
|
||||
})
|
|
@ -0,0 +1,20 @@
|
|||
import {
|
||||
Comment,
|
||||
Fragment,
|
||||
Static,
|
||||
Suspense,
|
||||
Teleport,
|
||||
Text,
|
||||
type VNode,
|
||||
createBlock,
|
||||
defineComponent,
|
||||
} from 'vue'
|
||||
import { expectType } from './utils'
|
||||
|
||||
expectType<VNode>(createBlock(Teleport))
|
||||
expectType<VNode>(createBlock(Text))
|
||||
expectType<VNode>(createBlock(Static))
|
||||
expectType<VNode>(createBlock(Comment))
|
||||
expectType<VNode>(createBlock(Fragment))
|
||||
expectType<VNode>(createBlock(Suspense))
|
||||
expectType<VNode>(createBlock(defineComponent({})))
|
|
@ -1,22 +1,29 @@
|
|||
import {
|
||||
describe,
|
||||
Component,
|
||||
type Component,
|
||||
type ComponentPublicInstance,
|
||||
type EmitsOptions,
|
||||
type FunctionalComponent,
|
||||
type PropType,
|
||||
type Ref,
|
||||
type SetupContext,
|
||||
type ShallowUnwrapRef,
|
||||
defineComponent,
|
||||
PropType,
|
||||
ref,
|
||||
Ref,
|
||||
expectError,
|
||||
expectType,
|
||||
ShallowUnwrapRef,
|
||||
FunctionalComponent,
|
||||
ComponentPublicInstance,
|
||||
toRefs
|
||||
} from './index'
|
||||
toRefs,
|
||||
} from 'vue'
|
||||
import { type IsAny, describe, expectAssignable, expectType } from './utils'
|
||||
|
||||
declare function extractComponentOptions<Props, RawBindings>(
|
||||
obj: Component<Props, RawBindings>
|
||||
declare function extractComponentOptions<
|
||||
Props,
|
||||
RawBindings,
|
||||
Emits extends EmitsOptions | Record<string, any[]>,
|
||||
Slots extends Record<string, any>,
|
||||
>(
|
||||
obj: Component<Props, RawBindings, any, any, any, Emits, Slots>,
|
||||
): {
|
||||
props: Props
|
||||
emits: Emits
|
||||
slots: Slots
|
||||
rawBindings: RawBindings
|
||||
setup: ShallowUnwrapRef<RawBindings>
|
||||
}
|
||||
|
@ -62,6 +69,7 @@ describe('object props', () => {
|
|||
ffff: Ref<(a: number, b: string) => { a: boolean }>
|
||||
validated: Ref<string | undefined>
|
||||
object: Ref<object | undefined>
|
||||
zzz: any
|
||||
}
|
||||
|
||||
describe('defineComponent', () => {
|
||||
|
@ -71,24 +79,24 @@ describe('object props', () => {
|
|||
// required should make property non-void
|
||||
b: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
e: Function,
|
||||
// default value should infer type and make it non-void
|
||||
bb: {
|
||||
default: 'hello'
|
||||
default: 'hello',
|
||||
},
|
||||
bbb: {
|
||||
// Note: default function value requires arrow syntax + explicit
|
||||
// annotation
|
||||
default: (props: any) => (props.bb as string) || 'foo'
|
||||
default: (props: any) => (props.bb as string) || 'foo',
|
||||
},
|
||||
// explicit type casting
|
||||
cc: Array as PropType<string[]>,
|
||||
// required + type casting
|
||||
dd: {
|
||||
type: Object as PropType<{ n: 1 }>,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
// return type
|
||||
ee: Function as PropType<() => string>,
|
||||
|
@ -96,41 +104,42 @@ describe('object props', () => {
|
|||
ff: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
// explicit type casting with constructor
|
||||
ccc: Array as () => string[],
|
||||
// required + contructor type casting
|
||||
// required + constructor type casting
|
||||
ddd: {
|
||||
type: Array as () => string[],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
// required + object return
|
||||
eee: {
|
||||
type: Function as PropType<() => { a: string }>,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
// required + arguments + object return
|
||||
fff: {
|
||||
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
hhh: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
// default + type casting
|
||||
ggg: {
|
||||
type: String as PropType<'foo' | 'bar'>,
|
||||
default: 'foo'
|
||||
default: 'foo',
|
||||
},
|
||||
// default + function
|
||||
ffff: {
|
||||
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
default: (_a: number, _b: string) => ({ a: true })
|
||||
default: (_a: number, _b: string) => ({ a: true }),
|
||||
},
|
||||
validated: {
|
||||
type: String,
|
||||
// validator requires explicit annotation
|
||||
validator: (val: unknown) => val !== ''
|
||||
validator: (val: unknown) => val !== '',
|
||||
},
|
||||
object: Object as PropType<object>
|
||||
object: Object as PropType<object>,
|
||||
zzz: Object as PropType<any>,
|
||||
},
|
||||
setup(props) {
|
||||
const refs = toRefs(props)
|
||||
|
@ -152,16 +161,18 @@ describe('object props', () => {
|
|||
expectType<ExpectedRefs['ffff']>(refs.ffff)
|
||||
expectType<ExpectedRefs['validated']>(refs.validated)
|
||||
expectType<ExpectedRefs['object']>(refs.object)
|
||||
expectType<IsAny<typeof props.zzz>>(true)
|
||||
|
||||
return {
|
||||
setupA: 1,
|
||||
setupB: ref(1),
|
||||
setupC: {
|
||||
a: ref(2)
|
||||
a: ref(2),
|
||||
},
|
||||
setupProps: props
|
||||
setupD: undefined as Ref<number> | undefined,
|
||||
setupProps: props,
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const { props, rawBindings, setup } = extractComponentOptions(MyComponent)
|
||||
|
@ -190,7 +201,7 @@ describe('object props', () => {
|
|||
expectType<Number>(rawBindings.setupA)
|
||||
expectType<Ref<Number>>(rawBindings.setupB)
|
||||
expectType<Ref<Number>>(rawBindings.setupC.a)
|
||||
expectType<Number>(rawBindings.setupA)
|
||||
expectType<Ref<Number> | undefined>(rawBindings.setupD)
|
||||
|
||||
// raw bindings props
|
||||
expectType<ExpectedProps['a']>(rawBindings.setupProps.a)
|
||||
|
@ -215,7 +226,7 @@ describe('object props', () => {
|
|||
expectType<Number>(setup.setupA)
|
||||
expectType<Number>(setup.setupB)
|
||||
expectType<Ref<Number>>(setup.setupC.a)
|
||||
expectType<Number>(setup.setupA)
|
||||
expectType<number | undefined>(setup.setupD)
|
||||
|
||||
// raw bindings props
|
||||
expectType<ExpectedProps['a']>(setup.setupProps.a)
|
||||
|
@ -239,6 +250,7 @@ describe('object props', () => {
|
|||
// instance
|
||||
const instance = new MyComponent()
|
||||
expectType<number>(instance.setupA)
|
||||
expectType<number | undefined>(instance.setupD)
|
||||
// @ts-expect-error
|
||||
instance.notExist
|
||||
})
|
||||
|
@ -250,24 +262,24 @@ describe('object props', () => {
|
|||
// required should make property non-void
|
||||
b: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
e: Function,
|
||||
// default value should infer type and make it non-void
|
||||
bb: {
|
||||
default: 'hello'
|
||||
default: 'hello',
|
||||
},
|
||||
bbb: {
|
||||
// Note: default function value requires arrow syntax + explicit
|
||||
// annotation
|
||||
default: (props: any) => (props.bb as string) || 'foo'
|
||||
default: (props: any) => (props.bb as string) || 'foo',
|
||||
},
|
||||
// explicit type casting
|
||||
cc: Array as PropType<string[]>,
|
||||
// required + type casting
|
||||
dd: {
|
||||
type: Object as PropType<{ n: 1 }>,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
// return type
|
||||
ee: Function as PropType<() => string>,
|
||||
|
@ -275,48 +287,48 @@ describe('object props', () => {
|
|||
ff: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
// explicit type casting with constructor
|
||||
ccc: Array as () => string[],
|
||||
// required + contructor type casting
|
||||
// required + constructor type casting
|
||||
ddd: {
|
||||
type: Array as () => string[],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
// required + object return
|
||||
eee: {
|
||||
type: Function as PropType<() => { a: string }>,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
// required + arguments + object return
|
||||
fff: {
|
||||
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
hhh: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
// default + type casting
|
||||
ggg: {
|
||||
type: String as PropType<'foo' | 'bar'>,
|
||||
default: 'foo'
|
||||
default: 'foo',
|
||||
},
|
||||
// default + function
|
||||
ffff: {
|
||||
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
default: (_a: number, _b: string) => ({ a: true })
|
||||
default: (_a: number, _b: string) => ({ a: true }),
|
||||
},
|
||||
validated: {
|
||||
type: String,
|
||||
// validator requires explicit annotation
|
||||
validator: (val: unknown) => val !== ''
|
||||
validator: (val: unknown) => val !== '',
|
||||
},
|
||||
object: Object as PropType<object>
|
||||
object: Object as PropType<object>,
|
||||
},
|
||||
|
||||
setup() {
|
||||
return {
|
||||
setupA: 1
|
||||
setupA: 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
} as const
|
||||
|
||||
const { props, rawBindings, setup } = extractComponentOptions(MyComponent)
|
||||
|
@ -355,15 +367,15 @@ describe('array props', () => {
|
|||
props: ['a', 'b'],
|
||||
setup() {
|
||||
return {
|
||||
c: 1
|
||||
c: 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const { props, rawBindings, setup } = extractComponentOptions(MyComponent)
|
||||
|
||||
// @ts-expect-error props should be readonly
|
||||
expectError((props.a = 1))
|
||||
props.a = 1
|
||||
expectType<any>(props.a)
|
||||
expectType<any>(props.b)
|
||||
|
||||
|
@ -376,15 +388,15 @@ describe('array props', () => {
|
|||
props: ['a', 'b'] as const,
|
||||
setup() {
|
||||
return {
|
||||
c: 1
|
||||
c: 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const { props, rawBindings, setup } = extractComponentOptions(MyComponent)
|
||||
|
||||
// @ts-expect-error props should be readonly
|
||||
expectError((props.a = 1))
|
||||
props.a = 1
|
||||
|
||||
// TODO infer the correct keys
|
||||
// expectType<any>(props.a)
|
||||
|
@ -400,9 +412,9 @@ describe('no props', () => {
|
|||
const MyComponent = defineComponent({
|
||||
setup() {
|
||||
return {
|
||||
setupA: 1
|
||||
setupA: 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const { rawBindings, setup } = extractComponentOptions(MyComponent)
|
||||
|
@ -421,9 +433,9 @@ describe('no props', () => {
|
|||
const MyComponent = {
|
||||
setup() {
|
||||
return {
|
||||
setupA: 1
|
||||
setupA: 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const { rawBindings, setup } = extractComponentOptions(MyComponent)
|
||||
|
@ -451,11 +463,27 @@ describe('functional', () => {
|
|||
})
|
||||
|
||||
describe('typed', () => {
|
||||
const MyComponent: FunctionalComponent<{ foo: number }> = (_, _2) => {}
|
||||
type Props = { foo: number }
|
||||
type Emits = { change: [value: string]; inc: [value: number] }
|
||||
type Slots = { default: (scope: { foo: string }) => any }
|
||||
|
||||
const { props } = extractComponentOptions(MyComponent)
|
||||
const MyComponent: FunctionalComponent<Props, Emits, Slots> = (
|
||||
props,
|
||||
{ emit, slots },
|
||||
) => {
|
||||
expectType<Props>(props)
|
||||
expectType<{
|
||||
(event: 'change', value: string): void
|
||||
(event: 'inc', value: number): void
|
||||
}>(emit)
|
||||
expectType<Slots>(slots)
|
||||
}
|
||||
|
||||
expectType<number>(props.foo)
|
||||
const { props, emits, slots } = extractComponentOptions(MyComponent)
|
||||
|
||||
expectType<Props>(props)
|
||||
expectType<Emits>(emits)
|
||||
expectType<Slots>(slots)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -470,3 +498,25 @@ describe('class', () => {
|
|||
|
||||
expectType<number>(props.foo)
|
||||
})
|
||||
|
||||
describe('SetupContext', () => {
|
||||
describe('can assign', () => {
|
||||
const wider: SetupContext<{ a: () => true; b: () => true }> = {} as any
|
||||
|
||||
expectAssignable<SetupContext<{ b: () => true }>>(wider)
|
||||
})
|
||||
|
||||
describe('short emits', () => {
|
||||
const {
|
||||
emit,
|
||||
}: SetupContext<{
|
||||
a: [val: string]
|
||||
b: [val: number]
|
||||
}> = {} as any
|
||||
|
||||
expectType<{
|
||||
(event: 'a', val: string): void
|
||||
(event: 'b', val: number): void
|
||||
}>(emit)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,139 @@
|
|||
import {
|
||||
type ComponentInstance,
|
||||
type ComponentPublicInstance,
|
||||
type FunctionalComponent,
|
||||
defineComponent,
|
||||
ref,
|
||||
} from 'vue'
|
||||
import { describe, expectType } from './utils'
|
||||
|
||||
describe('defineComponent', () => {
|
||||
const CompSetup = defineComponent({
|
||||
props: {
|
||||
test: String,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
a: 1,
|
||||
}
|
||||
},
|
||||
})
|
||||
const compSetup: ComponentInstance<typeof CompSetup> = {} as any
|
||||
|
||||
expectType<string | undefined>(compSetup.test)
|
||||
expectType<number>(compSetup.a)
|
||||
expectType<ComponentPublicInstance>(compSetup)
|
||||
})
|
||||
describe('functional component', () => {
|
||||
// Functional
|
||||
const CompFunctional: FunctionalComponent<{ test?: string }> = {} as any
|
||||
const compFunctional: ComponentInstance<typeof CompFunctional> = {} as any
|
||||
|
||||
expectType<string | undefined>(compFunctional.test)
|
||||
expectType<ComponentPublicInstance>(compFunctional)
|
||||
|
||||
const CompFunction: (props: { test?: string }) => any = {} as any
|
||||
const compFunction: ComponentInstance<typeof CompFunction> = {} as any
|
||||
|
||||
expectType<string | undefined>(compFunction.test)
|
||||
expectType<ComponentPublicInstance>(compFunction)
|
||||
})
|
||||
|
||||
describe('options component', () => {
|
||||
// Options
|
||||
const CompOptions = defineComponent({
|
||||
props: {
|
||||
test: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
a: 1,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
b() {
|
||||
return 'test'
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
func(a: string) {
|
||||
return true
|
||||
},
|
||||
},
|
||||
})
|
||||
const compOptions: ComponentInstance<typeof CompOptions> = {} as any
|
||||
expectType<string | undefined>(compOptions.test)
|
||||
expectType<number>(compOptions.a)
|
||||
expectType<(a: string) => boolean>(compOptions.func)
|
||||
expectType<ComponentPublicInstance>(compOptions)
|
||||
})
|
||||
|
||||
describe('object no defineComponent', () => {
|
||||
// object - no defineComponent
|
||||
|
||||
const CompObjectSetup = {
|
||||
props: {
|
||||
test: String,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
a: 1,
|
||||
}
|
||||
},
|
||||
}
|
||||
const compObjectSetup: ComponentInstance<typeof CompObjectSetup> = {} as any
|
||||
expectType<string | undefined>(compObjectSetup.test)
|
||||
expectType<number>(compObjectSetup.a)
|
||||
expectType<ComponentPublicInstance>(compObjectSetup)
|
||||
|
||||
const CompObjectData = {
|
||||
props: {
|
||||
test: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
a: 1,
|
||||
}
|
||||
},
|
||||
}
|
||||
const compObjectData: ComponentInstance<typeof CompObjectData> = {} as any
|
||||
expectType<string | undefined>(compObjectData.test)
|
||||
expectType<number>(compObjectData.a)
|
||||
expectType<ComponentPublicInstance>(compObjectData)
|
||||
|
||||
const CompObjectNoProps = {
|
||||
data() {
|
||||
return {
|
||||
a: 1,
|
||||
}
|
||||
},
|
||||
}
|
||||
const compObjectNoProps: ComponentInstance<typeof CompObjectNoProps> =
|
||||
{} as any
|
||||
expectType<string | undefined>(compObjectNoProps.test)
|
||||
expectType<number>(compObjectNoProps.a)
|
||||
expectType<ComponentPublicInstance>(compObjectNoProps)
|
||||
})
|
||||
|
||||
describe('Generic component', () => {
|
||||
const Comp = defineComponent(
|
||||
// TODO: babel plugin to auto infer runtime props options from type
|
||||
// similar to defineProps<{...}>()
|
||||
<T extends string | number>(props: { msg: T; list: T[] }) => {
|
||||
// use Composition API here like in <script setup>
|
||||
const count = ref(0)
|
||||
|
||||
return () => (
|
||||
// return a render function (both JSX and h() works)
|
||||
<div>
|
||||
{props.msg} {count.value}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
// defaults to known types since types are resolved on instantiation
|
||||
const comp: ComponentInstance<typeof Comp> = {} as any
|
||||
expectType<string | number>(comp.msg)
|
||||
expectType<Array<string | number>>(comp.list)
|
||||
})
|
|
@ -0,0 +1,73 @@
|
|||
import { type DefineComponent, type Directive, defineComponent } from 'vue'
|
||||
import { expectType } from './utils'
|
||||
|
||||
declare module 'vue' {
|
||||
interface ComponentCustomOptions {
|
||||
test?(n: number): void
|
||||
}
|
||||
|
||||
interface GlobalDirectives {
|
||||
test: Directive
|
||||
}
|
||||
|
||||
interface GlobalComponents {
|
||||
RouterView: DefineComponent<{}>
|
||||
}
|
||||
|
||||
interface ComponentCustomProperties {
|
||||
state?: 'stopped' | 'running'
|
||||
}
|
||||
|
||||
interface ComponentCustomProps {
|
||||
custom?: number
|
||||
}
|
||||
}
|
||||
|
||||
export const Custom = defineComponent({
|
||||
props: {
|
||||
bar: String,
|
||||
baz: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data: () => ({ counter: 0 }),
|
||||
|
||||
test(n) {
|
||||
expectType<number>(n)
|
||||
},
|
||||
|
||||
methods: {
|
||||
aMethod() {
|
||||
this.counter++
|
||||
this.state = 'running'
|
||||
this.$.appContext.config.globalProperties.state = 'running'
|
||||
|
||||
// @ts-expect-error
|
||||
this.notExisting
|
||||
// @ts-expect-error
|
||||
this.state = 'not valid'
|
||||
// @ts-expect-error
|
||||
this.$.appContext.config.globalProperties.state = 'not valid'
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expectType<Directive>(Custom.directives!.test)
|
||||
expectType<DefineComponent<{}>>(Custom.components!.RouterView)
|
||||
expectType<JSX.Element>(<Custom baz={1} />)
|
||||
expectType<JSX.Element>(<Custom custom={1} baz={1} />)
|
||||
expectType<JSX.Element>(<Custom bar="bar" baz={1} />)
|
||||
expectType<JSX.Element>(<Custom ref={''} bar="bar" baz={1} />)
|
||||
|
||||
// @ts-expect-error
|
||||
expectType<JSX.Element>(<Custom />)
|
||||
// @ts-expect-error
|
||||
;<Custom bar="bar" />
|
||||
// @ts-expect-error
|
||||
;<Custom baz="baz" />
|
||||
// @ts-expect-error
|
||||
;<Custom baz={1} notExist={1} />
|
||||
// @ts-expect-error
|
||||
;<Custom baz={1} custom="custom" />
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,135 @@
|
|||
import {
|
||||
type VueElementConstructor,
|
||||
defineComponent,
|
||||
defineCustomElement,
|
||||
} from 'vue'
|
||||
import { describe, expectType, test } from './utils'
|
||||
|
||||
describe('inject', () => {
|
||||
// with object inject
|
||||
defineCustomElement({
|
||||
props: {
|
||||
a: String,
|
||||
},
|
||||
inject: {
|
||||
foo: 'foo',
|
||||
bar: 'bar',
|
||||
},
|
||||
created() {
|
||||
expectType<unknown>(this.foo)
|
||||
expectType<unknown>(this.bar)
|
||||
// @ts-expect-error
|
||||
this.foobar = 1
|
||||
},
|
||||
})
|
||||
|
||||
// with array inject
|
||||
defineCustomElement({
|
||||
props: ['a', 'b'],
|
||||
inject: ['foo', 'bar'],
|
||||
created() {
|
||||
expectType<unknown>(this.foo)
|
||||
expectType<unknown>(this.bar)
|
||||
// @ts-expect-error
|
||||
this.foobar = 1
|
||||
},
|
||||
})
|
||||
|
||||
// with no props
|
||||
defineCustomElement({
|
||||
inject: {
|
||||
foo: {
|
||||
from: 'pbar',
|
||||
default: 'foo',
|
||||
},
|
||||
bar: {
|
||||
from: 'pfoo',
|
||||
default: 'bar',
|
||||
},
|
||||
},
|
||||
created() {
|
||||
expectType<unknown>(this.foo)
|
||||
expectType<unknown>(this.bar)
|
||||
// @ts-expect-error
|
||||
this.foobar = 1
|
||||
},
|
||||
})
|
||||
|
||||
// without inject
|
||||
defineCustomElement({
|
||||
props: ['a', 'b'],
|
||||
created() {
|
||||
// @ts-expect-error
|
||||
this.foo = 1
|
||||
// @ts-expect-error
|
||||
this.bar = 1
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('defineCustomElement using defineComponent return type', () => {
|
||||
test('with object emits', () => {
|
||||
const Comp1Vue = defineComponent({
|
||||
props: {
|
||||
a: String,
|
||||
},
|
||||
emits: {
|
||||
click: () => true,
|
||||
},
|
||||
})
|
||||
const Comp = defineCustomElement(Comp1Vue)
|
||||
expectType<VueElementConstructor>(Comp)
|
||||
|
||||
const instance = new Comp()
|
||||
expectType<string | undefined>(instance.a)
|
||||
instance.a = ''
|
||||
})
|
||||
|
||||
test('with array emits', () => {
|
||||
const Comp1Vue = defineComponent({
|
||||
props: {
|
||||
a: Number,
|
||||
},
|
||||
emits: ['click'],
|
||||
})
|
||||
const Comp = defineCustomElement(Comp1Vue)
|
||||
expectType<VueElementConstructor>(Comp)
|
||||
|
||||
const instance = new Comp()
|
||||
expectType<number | undefined>(instance.a)
|
||||
instance.a = 42
|
||||
})
|
||||
|
||||
test('with required props', () => {
|
||||
const Comp1Vue = defineComponent({
|
||||
props: {
|
||||
a: { type: Number, required: true },
|
||||
},
|
||||
})
|
||||
const Comp = defineCustomElement(Comp1Vue)
|
||||
expectType<VueElementConstructor>(Comp)
|
||||
|
||||
const instance = new Comp()
|
||||
expectType<number>(instance.a)
|
||||
instance.a = 42
|
||||
})
|
||||
|
||||
test('with default props', () => {
|
||||
const Comp1Vue = defineComponent({
|
||||
props: {
|
||||
a: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
validator: () => true,
|
||||
},
|
||||
},
|
||||
emits: ['click'],
|
||||
})
|
||||
const Comp = defineCustomElement(Comp1Vue)
|
||||
expectType<VueElementConstructor>(Comp)
|
||||
|
||||
const instance = new Comp()
|
||||
expectType<number>(instance.a)
|
||||
instance.a = 42
|
||||
})
|
||||
})
|
|
@ -0,0 +1,58 @@
|
|||
import { type Directive, type ObjectDirective, vModelText } from 'vue'
|
||||
import { describe, expectType } from './utils'
|
||||
|
||||
type ExtractBinding<T> = T extends (
|
||||
el: any,
|
||||
binding: infer B,
|
||||
vnode: any,
|
||||
prev: any,
|
||||
) => any
|
||||
? B
|
||||
: never
|
||||
|
||||
declare function testDirective<
|
||||
Value,
|
||||
Modifiers extends string = string,
|
||||
Arg extends string = string,
|
||||
>(): ExtractBinding<Directive<any, Value, Modifiers, Arg>>
|
||||
|
||||
describe('vmodel', () => {
|
||||
expectType<ObjectDirective<any, any, 'trim' | 'number' | 'lazy', string>>(
|
||||
vModelText,
|
||||
)
|
||||
// @ts-expect-error
|
||||
expectType<ObjectDirective<any, any, 'not-valid', string>>(vModelText)
|
||||
})
|
||||
|
||||
describe('custom', () => {
|
||||
expectType<{
|
||||
value: number
|
||||
oldValue: number | null
|
||||
arg?: 'Arg'
|
||||
modifiers: Record<'a' | 'b', boolean>
|
||||
}>(testDirective<number, 'a' | 'b', 'Arg'>())
|
||||
|
||||
expectType<{
|
||||
value: number
|
||||
oldValue: number | null
|
||||
arg?: 'Arg'
|
||||
modifiers: Record<'a' | 'b', boolean>
|
||||
// @ts-expect-error
|
||||
}>(testDirective<number, 'a', 'Arg'>())
|
||||
|
||||
expectType<{
|
||||
value: number
|
||||
oldValue: number | null
|
||||
arg?: 'Arg'
|
||||
modifiers: Record<'a' | 'b', boolean>
|
||||
// @ts-expect-error
|
||||
}>(testDirective<number, 'a' | 'b', 'Argx'>())
|
||||
|
||||
expectType<{
|
||||
value: number
|
||||
oldValue: number | null
|
||||
arg?: 'Arg'
|
||||
modifiers: Record<'a' | 'b', boolean>
|
||||
// @ts-expect-error
|
||||
}>(testDirective<string, 'a' | 'b', 'Arg'>())
|
||||
})
|
|
@ -0,0 +1,30 @@
|
|||
import type { ExtractPropTypes, ExtractPublicPropTypes } from 'vue'
|
||||
import { type Prettify, expectType } from './utils'
|
||||
|
||||
const propsOptions = {
|
||||
foo: {
|
||||
default: 1,
|
||||
},
|
||||
bar: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
baz: Boolean,
|
||||
qux: Array,
|
||||
} as const
|
||||
|
||||
// internal facing props
|
||||
declare const props: Prettify<ExtractPropTypes<typeof propsOptions>>
|
||||
|
||||
expectType<number>(props.foo)
|
||||
expectType<string>(props.bar)
|
||||
expectType<boolean>(props.baz)
|
||||
expectType<unknown[] | undefined>(props.qux)
|
||||
|
||||
// external facing props
|
||||
declare const publicProps: Prettify<ExtractPublicPropTypes<typeof propsOptions>>
|
||||
|
||||
expectType<number | undefined>(publicProps.foo)
|
||||
expectType<string>(publicProps.bar)
|
||||
expectType<boolean | undefined>(publicProps.baz)
|
||||
expectType<unknown[] | undefined>(publicProps.qux)
|
|
@ -1,11 +1,11 @@
|
|||
import {
|
||||
h,
|
||||
type Component,
|
||||
type FunctionalComponent,
|
||||
Text,
|
||||
FunctionalComponent,
|
||||
expectError,
|
||||
expectType,
|
||||
Component
|
||||
} from './index'
|
||||
type VNode,
|
||||
h,
|
||||
} from 'vue'
|
||||
import { expectType } from './utils'
|
||||
|
||||
// simple function signature
|
||||
const Foo = (props: { foo: number }) => h(Text, null, props.foo)
|
||||
|
@ -15,11 +15,11 @@ expectType<JSX.Element>(<Foo foo={1} />)
|
|||
expectType<JSX.Element>(<Foo foo={1} key="1" />)
|
||||
expectType<JSX.Element>(<Foo foo={1} ref="ref" />)
|
||||
// @ts-expect-error
|
||||
expectError(<Foo />)
|
||||
;<Foo />
|
||||
// @ts-expect-error
|
||||
expectError(<Foo foo="bar" />)
|
||||
;<Foo foo="bar" />
|
||||
// @ts-expect-error
|
||||
expectError(<Foo baz="bar" />)
|
||||
;<Foo baz="bar" />
|
||||
|
||||
// Explicit signature with props + emits
|
||||
const Bar: FunctionalComponent<
|
||||
|
@ -30,34 +30,34 @@ const Bar: FunctionalComponent<
|
|||
|
||||
emit('update', 123)
|
||||
// @ts-expect-error
|
||||
expectError(emit('nope'))
|
||||
emit('nope')
|
||||
// @ts-expect-error
|
||||
expectError(emit('update'))
|
||||
emit('update')
|
||||
// @ts-expect-error
|
||||
expectError(emit('update', 'nope'))
|
||||
emit('update', 'nope')
|
||||
}
|
||||
|
||||
// assigning runtime options
|
||||
Bar.props = {
|
||||
foo: Number
|
||||
foo: Number,
|
||||
}
|
||||
// @ts-expect-error
|
||||
expectError((Bar.props = { foo: String }))
|
||||
Bar.props = { foo: String }
|
||||
|
||||
Bar.emits = {
|
||||
update: value => value > 1
|
||||
update: value => value > 1,
|
||||
}
|
||||
// @ts-expect-error
|
||||
expectError((Bar.emits = { baz: () => void 0 }))
|
||||
Bar.emits = { baz: () => void 0 }
|
||||
|
||||
// TSX
|
||||
expectType<JSX.Element>(<Bar foo={1} />)
|
||||
expectType<JSX.Element>(<Bar foo={1} onUpdate={() => {}} />)
|
||||
// @ts-expect-error
|
||||
expectError(<Foo />)
|
||||
;<Foo />
|
||||
// @ts-expect-error
|
||||
expectError(<Bar foo="bar" />)
|
||||
;<Bar foo="bar" />
|
||||
// @ts-expect-error
|
||||
expectError(<Foo baz="bar" />)
|
||||
;<Foo baz="bar" />
|
||||
|
||||
const Baz: FunctionalComponent<{}, string[]> = (props, { emit }) => {
|
||||
expectType<{}>(props)
|
||||
|
@ -74,3 +74,29 @@ const Qux: FunctionalComponent<{}, ['foo', 'bar']> = (props, { emit }) => {
|
|||
}
|
||||
|
||||
expectType<Component>(Qux)
|
||||
|
||||
const Quux: FunctionalComponent<
|
||||
{},
|
||||
{},
|
||||
{
|
||||
default: { foo: number }
|
||||
optional?: { foo: number }
|
||||
}
|
||||
> = (props, { emit, slots }) => {
|
||||
expectType<{
|
||||
default: (scope: { foo: number }) => VNode[]
|
||||
optional?: (scope: { foo: number }) => VNode[]
|
||||
}>(slots)
|
||||
|
||||
slots.default({ foo: 123 })
|
||||
// @ts-expect-error
|
||||
slots.default({ foo: 'fesf' })
|
||||
|
||||
slots.optional?.({ foo: 123 })
|
||||
// @ts-expect-error
|
||||
slots.optional?.({ foo: 'fesf' })
|
||||
// @ts-expect-error
|
||||
slots.optional({ foo: 123 })
|
||||
}
|
||||
expectType<Component>(Quux)
|
||||
;<Quux />
|
|
@ -1,38 +1,50 @@
|
|||
import {
|
||||
describe,
|
||||
h,
|
||||
defineComponent,
|
||||
ref,
|
||||
type Component,
|
||||
type DefineComponent,
|
||||
Fragment,
|
||||
Teleport,
|
||||
type FunctionalComponent,
|
||||
Suspense,
|
||||
Component,
|
||||
expectError,
|
||||
expectAssignable,
|
||||
resolveComponent
|
||||
} from './index'
|
||||
Teleport,
|
||||
type VNode,
|
||||
defineComponent,
|
||||
h,
|
||||
ref,
|
||||
resolveComponent,
|
||||
} from 'vue'
|
||||
import { describe, expectAssignable, expectType } from './utils'
|
||||
|
||||
describe('h inference w/ element', () => {
|
||||
// key
|
||||
h('div', { key: 1 })
|
||||
h('div', { key: 'foo' })
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { key: [] }))
|
||||
h('div', { key: [] })
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { key: {} }))
|
||||
h('div', { key: {} })
|
||||
// ref
|
||||
h('div', { ref: 'foo' })
|
||||
h('div', { ref: ref(null) })
|
||||
h('div', { ref: _el => {} })
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { ref: [] }))
|
||||
h('div', { ref: [] })
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { ref: {} }))
|
||||
h('div', { ref: {} })
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { ref: 123 }))
|
||||
h('div', { ref: 123 })
|
||||
// slots
|
||||
const slots = { default: () => {} } // RawSlots
|
||||
h('div', {}, slots)
|
||||
// events
|
||||
h('div', {
|
||||
onClick: e => {
|
||||
expectType<MouseEvent>(e)
|
||||
},
|
||||
})
|
||||
h('input', {
|
||||
onFocus(e) {
|
||||
expectType<FocusEvent>(e)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('h inference w/ Fragment', () => {
|
||||
|
@ -40,19 +52,20 @@ describe('h inference w/ Fragment', () => {
|
|||
h(Fragment, ['hello'])
|
||||
h(Fragment, { key: 123 }, ['hello'])
|
||||
// @ts-expect-error
|
||||
expectError(h(Fragment, 'foo'))
|
||||
h(Fragment, 'foo')
|
||||
// @ts-expect-error
|
||||
expectError(h(Fragment, { key: 123 }, 'bar'))
|
||||
h(Fragment, { key: 123 }, 'bar')
|
||||
})
|
||||
|
||||
describe('h inference w/ Teleport', () => {
|
||||
h(Teleport, { to: '#foo' }, 'hello')
|
||||
h(Teleport, { to: '#foo' }, { default() {} })
|
||||
// @ts-expect-error
|
||||
expectError(h(Teleport))
|
||||
h(Teleport)
|
||||
// @ts-expect-error
|
||||
expectError(h(Teleport, {}))
|
||||
h(Teleport, {})
|
||||
// @ts-expect-error
|
||||
expectError(h(Teleport, { to: '#foo' }))
|
||||
h(Teleport, { to: '#foo' })
|
||||
})
|
||||
|
||||
describe('h inference w/ Suspense', () => {
|
||||
|
@ -60,29 +73,51 @@ describe('h inference w/ Suspense', () => {
|
|||
h(Suspense, 'foo')
|
||||
h(Suspense, () => 'foo')
|
||||
h(Suspense, null, {
|
||||
default: () => 'foo'
|
||||
default: () => 'foo',
|
||||
})
|
||||
// @ts-expect-error
|
||||
expectError(h(Suspense, { onResolve: 1 }))
|
||||
h(Suspense, { onResolve: 1 })
|
||||
})
|
||||
|
||||
declare const fc: FunctionalComponent<
|
||||
{
|
||||
foo: string
|
||||
bar?: number
|
||||
onClick: (evt: MouseEvent) => void
|
||||
},
|
||||
['click'],
|
||||
{
|
||||
default: () => VNode
|
||||
title: (scope: { id: number }) => VNode
|
||||
}
|
||||
>
|
||||
declare const vnode: VNode
|
||||
describe('h inference w/ functional component', () => {
|
||||
const Func = (_props: { foo: string; bar?: number }) => ''
|
||||
h(Func, { foo: 'hello' })
|
||||
h(Func, { foo: 'hello', bar: 123 })
|
||||
// @ts-expect-error
|
||||
expectError(h(Func, { foo: 123 }))
|
||||
h(Func, { foo: 123 })
|
||||
// @ts-expect-error
|
||||
expectError(h(Func, {}))
|
||||
h(Func, {})
|
||||
// @ts-expect-error
|
||||
expectError(h(Func, { bar: 123 }))
|
||||
h(Func, { bar: 123 })
|
||||
|
||||
h(
|
||||
fc,
|
||||
{ foo: 'hello', onClick: () => {} },
|
||||
{
|
||||
default: () => vnode,
|
||||
title: ({ id }: { id: number }) => vnode,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
describe('h support w/ plain object component', () => {
|
||||
const Foo = {
|
||||
props: {
|
||||
foo: String
|
||||
}
|
||||
foo: String,
|
||||
},
|
||||
}
|
||||
h(Foo, { foo: 'ok' })
|
||||
h(Foo, { foo: 'ok', class: 'extra' })
|
||||
|
@ -95,9 +130,9 @@ describe('h inference w/ defineComponent', () => {
|
|||
foo: String,
|
||||
bar: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
h(Foo, { bar: 1 })
|
||||
|
@ -105,11 +140,11 @@ describe('h inference w/ defineComponent', () => {
|
|||
// should allow extraneous props (attrs fallthrough)
|
||||
h(Foo, { bar: 1, foo: 'ok', class: 'extra' })
|
||||
// @ts-expect-error should fail on missing required prop
|
||||
expectError(h(Foo, {}))
|
||||
h(Foo, {})
|
||||
// @ts-expect-error
|
||||
expectError(h(Foo, { foo: 'ok' }))
|
||||
h(Foo, { foo: 'ok' })
|
||||
// @ts-expect-error should fail on wrong type
|
||||
expectError(h(Foo, { bar: 1, foo: 1 }))
|
||||
h(Foo, { bar: 1, foo: 1 })
|
||||
})
|
||||
|
||||
// describe('h inference w/ defineComponent + optional props', () => {
|
||||
|
@ -122,11 +157,11 @@ describe('h inference w/ defineComponent', () => {
|
|||
// // should allow extraneous props (attrs fallthrough)
|
||||
// h(Foo, { bar: 1, foo: 'ok', class: 'extra' })
|
||||
// // @ts-expect-error should fail on missing required prop
|
||||
// expectError(h(Foo, {}))
|
||||
// h(Foo, {})
|
||||
// // @ts-expect-error
|
||||
// expectError(h(Foo, { foo: 'ok' }))
|
||||
// h(Foo, { foo: 'ok' })
|
||||
// // @ts-expect-error should fail on wrong type
|
||||
// expectError(h(Foo, { bar: 1, foo: 1 }))
|
||||
// h(Foo, { bar: 1, foo: 1 })
|
||||
// })
|
||||
|
||||
// describe('h inference w/ defineComponent + direct function', () => {
|
||||
|
@ -137,19 +172,18 @@ describe('h inference w/ defineComponent', () => {
|
|||
// // should allow extraneous props (attrs fallthrough)
|
||||
// h(Foo, { bar: 1, foo: 'ok', class: 'extra' })
|
||||
// // @ts-expect-error should fail on missing required prop
|
||||
// expectError(h(Foo, {}))
|
||||
// h(Foo, {})
|
||||
// // @ts-expect-error
|
||||
// expectError(h(Foo, { foo: 'ok' }))
|
||||
// h(Foo, { foo: 'ok' })
|
||||
// // @ts-expect-error should fail on wrong type
|
||||
// expectError(h(Foo, { bar: 1, foo: 1 }))
|
||||
// h(Foo, { bar: 1, foo: 1 })
|
||||
// })
|
||||
|
||||
// #922
|
||||
// #922 and #3218
|
||||
describe('h support for generic component type', () => {
|
||||
function foo(bar: Component) {
|
||||
h(bar)
|
||||
h(bar, 'hello')
|
||||
// @ts-expect-error
|
||||
h(bar, { id: 'ok' }, 'hello')
|
||||
}
|
||||
foo({})
|
||||
|
@ -159,7 +193,7 @@ describe('h support for generic component type', () => {
|
|||
describe('describeComponent extends Component', () => {
|
||||
// functional
|
||||
expectAssignable<Component>(
|
||||
defineComponent((_props: { foo?: string; bar: number }) => {})
|
||||
defineComponent((_props: { foo?: string; bar: number }) => () => {}),
|
||||
)
|
||||
|
||||
// typed props
|
||||
|
@ -168,8 +202,8 @@ describe('describeComponent extends Component', () => {
|
|||
// prop arrays
|
||||
expectAssignable<Component>(
|
||||
defineComponent({
|
||||
props: ['a', 'b']
|
||||
})
|
||||
props: ['a', 'b'],
|
||||
}),
|
||||
)
|
||||
|
||||
// prop object
|
||||
|
@ -179,10 +213,10 @@ describe('describeComponent extends Component', () => {
|
|||
foo: String,
|
||||
bar: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
})
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -192,9 +226,9 @@ describe('component w/ props w/ default value', () => {
|
|||
props: {
|
||||
message: {
|
||||
type: String,
|
||||
default: 'hello'
|
||||
}
|
||||
}
|
||||
default: 'hello',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
h(MyComponent, {})
|
||||
|
@ -204,8 +238,8 @@ describe('component w/ props w/ default value', () => {
|
|||
describe('Boolean prop implicit false', () => {
|
||||
const MyComponent = defineComponent({
|
||||
props: {
|
||||
visible: Boolean
|
||||
}
|
||||
visible: Boolean,
|
||||
},
|
||||
})
|
||||
|
||||
h(MyComponent, {})
|
||||
|
@ -214,22 +248,37 @@ describe('Boolean prop implicit false', () => {
|
|||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
h(RequiredComponent, {
|
||||
visible: true
|
||||
visible: true,
|
||||
})
|
||||
// @ts-expect-error
|
||||
expectError(h(RequiredComponent, {}))
|
||||
h(RequiredComponent, {})
|
||||
})
|
||||
|
||||
// #2357
|
||||
describe('resolveComponent should work', () => {
|
||||
h(resolveComponent('test'))
|
||||
h(resolveComponent('test'), {
|
||||
message: '1'
|
||||
message: '1',
|
||||
})
|
||||
})
|
||||
|
||||
// #5431
|
||||
describe('h should work with multiple types', () => {
|
||||
const serializers = {
|
||||
Paragraph: 'p',
|
||||
Component: {} as Component,
|
||||
DefineComponent: {} as DefineComponent,
|
||||
}
|
||||
|
||||
const sampleComponent = serializers['' as keyof typeof serializers]
|
||||
|
||||
h(sampleComponent)
|
||||
h(sampleComponent, {})
|
||||
h(sampleComponent, {}, [])
|
||||
})
|
|
@ -0,0 +1,61 @@
|
|||
import {
|
||||
type InjectionKey,
|
||||
type Ref,
|
||||
createApp,
|
||||
defineComponent,
|
||||
inject,
|
||||
provide,
|
||||
ref,
|
||||
} from 'vue'
|
||||
import { expectType } from './utils'
|
||||
|
||||
// non-symbol keys
|
||||
provide('foo', 123)
|
||||
provide(123, 123)
|
||||
|
||||
const key: InjectionKey<number> = Symbol()
|
||||
|
||||
provide(key, 1)
|
||||
// @ts-expect-error
|
||||
provide(key, 'foo')
|
||||
// @ts-expect-error
|
||||
provide(key, null)
|
||||
|
||||
expectType<number | undefined>(inject(key))
|
||||
expectType<number>(inject(key, 1))
|
||||
expectType<number>(inject(key, () => 1, true /* treatDefaultAsFactory */))
|
||||
|
||||
expectType<() => number>(inject('foo', () => 1))
|
||||
expectType<() => number>(inject('foo', () => 1, false))
|
||||
expectType<number>(inject('foo', () => 1, true))
|
||||
|
||||
// #8201
|
||||
type Cube = {
|
||||
size: number
|
||||
}
|
||||
|
||||
const injectionKeyRef = Symbol('key') as InjectionKey<Ref<Cube>>
|
||||
|
||||
// @ts-expect-error
|
||||
provide(injectionKeyRef, ref({}))
|
||||
|
||||
// naive-ui: explicit provide type parameter
|
||||
provide<Cube>('cube', { size: 123 })
|
||||
provide<Cube>(123, { size: 123 })
|
||||
provide<Cube>(injectionKeyRef, { size: 123 })
|
||||
|
||||
// @ts-expect-error
|
||||
provide<Cube>('cube', { size: 'foo' })
|
||||
// @ts-expect-error
|
||||
provide<Cube>(123, { size: 'foo' })
|
||||
|
||||
// #10602
|
||||
const app = createApp({})
|
||||
// @ts-expect-error
|
||||
app.provide(injectionKeyRef, ref({}))
|
||||
|
||||
defineComponent({
|
||||
provide: {
|
||||
[injectionKeyRef]: { size: 'foo' },
|
||||
},
|
||||
})
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "dts-test",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"vue": "workspace:*",
|
||||
"dts-built-test": "workspace:*"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
import {
|
||||
type Ref,
|
||||
markRaw,
|
||||
reactive,
|
||||
readonly,
|
||||
ref,
|
||||
shallowReadonly,
|
||||
} from 'vue'
|
||||
import { describe, expectType } from './utils'
|
||||
|
||||
describe('should support DeepReadonly', () => {
|
||||
const r = readonly({ obj: { k: 'v' } })
|
||||
// @ts-expect-error
|
||||
r.obj = {}
|
||||
// @ts-expect-error
|
||||
r.obj.k = 'x'
|
||||
})
|
||||
|
||||
// #4180
|
||||
describe('readonly ref', () => {
|
||||
const r = readonly(ref({ count: 1 }))
|
||||
expectType<Ref>(r)
|
||||
})
|
||||
|
||||
describe('should support markRaw', () => {
|
||||
class Test<T> {
|
||||
item = {} as Ref<T>
|
||||
}
|
||||
const test = new Test<number>()
|
||||
const plain = {
|
||||
ref: ref(1),
|
||||
}
|
||||
|
||||
const r = reactive({
|
||||
class: {
|
||||
raw: markRaw(test),
|
||||
reactive: test,
|
||||
},
|
||||
plain: {
|
||||
raw: markRaw(plain),
|
||||
reactive: plain,
|
||||
},
|
||||
})
|
||||
|
||||
expectType<Test<number>>(r.class.raw)
|
||||
// @ts-expect-error it should unwrap
|
||||
expectType<Test<number>>(r.class.reactive)
|
||||
|
||||
expectType<Ref<number>>(r.plain.raw.ref)
|
||||
// @ts-expect-error it should unwrap
|
||||
expectType<Ref<number>>(r.plain.reactive.ref)
|
||||
})
|
||||
|
||||
describe('shallowReadonly ref unwrap', () => {
|
||||
const r = shallowReadonly({ count: { n: ref(1) } })
|
||||
// @ts-expect-error
|
||||
r.count = 2
|
||||
expectType<Ref>(r.count.n)
|
||||
r.count.n.value = 123
|
||||
})
|
||||
|
||||
// #3819
|
||||
describe('should unwrap tuple correctly', () => {
|
||||
const readonlyTuple = [ref(0)] as const
|
||||
const reactiveReadonlyTuple = reactive(readonlyTuple)
|
||||
expectType<Ref<number>>(reactiveReadonlyTuple[0])
|
||||
|
||||
const tuple: [Ref<number>] = [ref(0)]
|
||||
const reactiveTuple = reactive(tuple)
|
||||
expectType<Ref<number>>(reactiveTuple[0])
|
||||
})
|
||||
|
||||
describe('should unwrap Map correctly', () => {
|
||||
const map = reactive(new Map<string, Ref<number>>())
|
||||
expectType<Ref<number>>(map.get('a')!)
|
||||
|
||||
const map2 = reactive(new Map<string, { wrap: Ref<number> }>())
|
||||
expectType<number>(map2.get('a')!.wrap)
|
||||
|
||||
const wm = reactive(new WeakMap<object, Ref<number>>())
|
||||
expectType<Ref<number>>(wm.get({})!)
|
||||
|
||||
const wm2 = reactive(new WeakMap<object, { wrap: Ref<number> }>())
|
||||
expectType<number>(wm2.get({})!.wrap)
|
||||
})
|
||||
|
||||
describe('should unwrap extended Map correctly', () => {
|
||||
class ExtendendMap1 extends Map<string, { wrap: Ref<number> }> {
|
||||
foo = ref('foo')
|
||||
bar = 1
|
||||
}
|
||||
|
||||
const emap1 = reactive(new ExtendendMap1())
|
||||
expectType<string>(emap1.foo)
|
||||
expectType<number>(emap1.bar)
|
||||
expectType<number>(emap1.get('a')!.wrap)
|
||||
})
|
||||
|
||||
describe('should unwrap Set correctly', () => {
|
||||
const set = reactive(new Set<Ref<number>>())
|
||||
expectType<Set<Ref<number>>>(set)
|
||||
|
||||
const set2 = reactive(new Set<{ wrap: Ref<number> }>())
|
||||
expectType<Set<{ wrap: number }>>(set2)
|
||||
|
||||
const ws = reactive(new WeakSet<Ref<number>>())
|
||||
expectType<WeakSet<Ref<number>>>(ws)
|
||||
|
||||
const ws2 = reactive(new WeakSet<{ wrap: Ref<number> }>())
|
||||
expectType<WeakSet<{ wrap: number }>>(ws2)
|
||||
})
|
||||
|
||||
describe('should unwrap extended Set correctly', () => {
|
||||
class ExtendendSet1 extends Set<{ wrap: Ref<number> }> {
|
||||
foo = ref('foo')
|
||||
bar = 1
|
||||
}
|
||||
|
||||
const eset1 = reactive(new ExtendendSet1())
|
||||
expectType<string>(eset1.foo)
|
||||
expectType<number>(eset1.bar)
|
||||
})
|
||||
|
||||
describe('should not error when assignment', () => {
|
||||
const arr = reactive([''])
|
||||
let record: Record<number, string>
|
||||
record = arr
|
||||
expectType<string>(record[0])
|
||||
let record2: { [key: number]: string }
|
||||
record2 = arr
|
||||
expectType<string>(record2[0])
|
||||
})
|
|
@ -0,0 +1,523 @@
|
|||
import {
|
||||
type ComputedRef,
|
||||
type MaybeRef,
|
||||
type MaybeRefOrGetter,
|
||||
type Ref,
|
||||
type ShallowRef,
|
||||
type ToRefs,
|
||||
type WritableComputedRef,
|
||||
computed,
|
||||
isRef,
|
||||
proxyRefs,
|
||||
reactive,
|
||||
readonly,
|
||||
ref,
|
||||
shallowReactive,
|
||||
shallowRef,
|
||||
toRef,
|
||||
toRefs,
|
||||
toValue,
|
||||
unref,
|
||||
useTemplateRef,
|
||||
} from 'vue'
|
||||
import { type IsAny, type IsUnion, describe, expectType } from './utils'
|
||||
|
||||
function plainType(arg: number | Ref<number>) {
|
||||
// ref coercing
|
||||
const coerced = ref(arg)
|
||||
expectType<Ref<number>>(coerced)
|
||||
|
||||
// isRef as type guard
|
||||
if (isRef(arg)) {
|
||||
expectType<Ref<number>>(arg)
|
||||
}
|
||||
|
||||
// ref unwrapping
|
||||
expectType<number>(unref(arg))
|
||||
expectType<number>(toValue(arg))
|
||||
expectType<number>(toValue(() => 123))
|
||||
|
||||
// ref inner type should be unwrapped
|
||||
const nestedRef = ref({
|
||||
foo: ref(1),
|
||||
})
|
||||
expectType<{ foo: number }>(nestedRef.value)
|
||||
|
||||
// ref boolean
|
||||
const falseRef = ref(false)
|
||||
expectType<Ref<boolean>>(falseRef)
|
||||
expectType<boolean>(falseRef.value)
|
||||
|
||||
// ref true
|
||||
const trueRef = ref<true>(true)
|
||||
expectType<Ref<true>>(trueRef)
|
||||
expectType<true>(trueRef.value)
|
||||
|
||||
// tuple
|
||||
expectType<[number, string]>(unref(ref([1, '1'])))
|
||||
|
||||
interface IteratorFoo {
|
||||
[Symbol.iterator]: any
|
||||
}
|
||||
|
||||
// with symbol
|
||||
expectType<Ref<IteratorFoo | null | undefined>>(
|
||||
ref<IteratorFoo | null | undefined>(),
|
||||
)
|
||||
|
||||
// should not unwrap ref inside arrays
|
||||
const arr = ref([1, new Map<string, any>(), ref('1')]).value
|
||||
const value = arr[0]
|
||||
if (isRef(value)) {
|
||||
expectType<Ref>(value)
|
||||
} else if (typeof value === 'number') {
|
||||
expectType<number>(value)
|
||||
} else {
|
||||
// should narrow down to Map type
|
||||
// and not contain any Ref type
|
||||
expectType<Map<string, any>>(value)
|
||||
}
|
||||
|
||||
// should still unwrap in objects nested in arrays
|
||||
const arr2 = ref([{ a: ref(1) }]).value
|
||||
expectType<number>(arr2[0].a)
|
||||
|
||||
// any value should return Ref<any>, not any
|
||||
const a = ref(1 as any)
|
||||
expectType<IsAny<typeof a>>(false)
|
||||
}
|
||||
|
||||
plainType(1)
|
||||
|
||||
function bailType(arg: HTMLElement | Ref<HTMLElement>) {
|
||||
// ref coercing
|
||||
const coerced = ref(arg)
|
||||
expectType<Ref<HTMLElement>>(coerced)
|
||||
|
||||
// isRef as type guard
|
||||
if (isRef(arg)) {
|
||||
expectType<Ref<HTMLElement>>(arg)
|
||||
}
|
||||
|
||||
// ref unwrapping
|
||||
expectType<HTMLElement>(unref(arg))
|
||||
|
||||
// ref inner type should be unwrapped
|
||||
const nestedRef = ref({ foo: ref(document.createElement('DIV')) })
|
||||
|
||||
expectType<Ref<{ foo: HTMLElement }>>(nestedRef)
|
||||
expectType<{ foo: HTMLElement }>(nestedRef.value)
|
||||
}
|
||||
const el = document.createElement('DIV')
|
||||
bailType(el)
|
||||
|
||||
function withSymbol() {
|
||||
const customSymbol = Symbol()
|
||||
const obj = {
|
||||
[Symbol.asyncIterator]: ref(1),
|
||||
[Symbol.hasInstance]: { a: ref('a') },
|
||||
[Symbol.isConcatSpreadable]: { b: ref(true) },
|
||||
[Symbol.iterator]: [ref(1)],
|
||||
[Symbol.match]: new Set<Ref<number>>(),
|
||||
[Symbol.matchAll]: new Map<number, Ref<string>>(),
|
||||
[Symbol.replace]: { arr: [ref('a')] },
|
||||
[Symbol.search]: { set: new Set<Ref<number>>() },
|
||||
[Symbol.species]: { map: new Map<number, Ref<string>>() },
|
||||
[Symbol.split]: new WeakSet<Ref<boolean>>(),
|
||||
[Symbol.toPrimitive]: new WeakMap<Ref<boolean>, string>(),
|
||||
[Symbol.toStringTag]: { weakSet: new WeakSet<Ref<boolean>>() },
|
||||
[Symbol.unscopables]: { weakMap: new WeakMap<Ref<boolean>, string>() },
|
||||
[customSymbol]: { arr: [ref(1)] },
|
||||
}
|
||||
|
||||
const objRef = ref(obj)
|
||||
|
||||
expectType<Ref<number>>(objRef.value[Symbol.asyncIterator])
|
||||
expectType<{ a: Ref<string> }>(objRef.value[Symbol.hasInstance])
|
||||
expectType<{ b: Ref<boolean> }>(objRef.value[Symbol.isConcatSpreadable])
|
||||
expectType<Ref<number>[]>(objRef.value[Symbol.iterator])
|
||||
expectType<Set<Ref<number>>>(objRef.value[Symbol.match])
|
||||
expectType<Map<number, Ref<string>>>(objRef.value[Symbol.matchAll])
|
||||
expectType<{ arr: Ref<string>[] }>(objRef.value[Symbol.replace])
|
||||
expectType<{ set: Set<Ref<number>> }>(objRef.value[Symbol.search])
|
||||
expectType<{ map: Map<number, Ref<string>> }>(objRef.value[Symbol.species])
|
||||
expectType<WeakSet<Ref<boolean>>>(objRef.value[Symbol.split])
|
||||
expectType<WeakMap<Ref<boolean>, string>>(objRef.value[Symbol.toPrimitive])
|
||||
expectType<{ weakSet: WeakSet<Ref<boolean>> }>(
|
||||
objRef.value[Symbol.toStringTag],
|
||||
)
|
||||
expectType<{ weakMap: WeakMap<Ref<boolean>, string> }>(
|
||||
objRef.value[Symbol.unscopables],
|
||||
)
|
||||
expectType<{ arr: Ref<number>[] }>(objRef.value[customSymbol])
|
||||
}
|
||||
|
||||
withSymbol()
|
||||
|
||||
const state = reactive({
|
||||
foo: {
|
||||
value: 1,
|
||||
label: 'bar',
|
||||
},
|
||||
})
|
||||
|
||||
expectType<string>(state.foo.label)
|
||||
|
||||
describe('ref with generic', <T extends { name: string }>() => {
|
||||
const r = {} as T
|
||||
const s = ref(r)
|
||||
expectType<string>(s.value.name)
|
||||
|
||||
const rr = {} as MaybeRef<T>
|
||||
// should at least allow casting
|
||||
const ss = ref(rr) as Ref<T>
|
||||
expectType<string>(ss.value.name)
|
||||
})
|
||||
|
||||
describe('allow getter and setter types to be unrelated', <T>() => {
|
||||
const a = { b: ref(0) }
|
||||
const c = ref(a)
|
||||
c.value = a
|
||||
|
||||
const d = {} as T
|
||||
const e = ref(d)
|
||||
e.value = d
|
||||
|
||||
const f = ref(ref(0))
|
||||
expectType<number>(f.value)
|
||||
// @ts-expect-error
|
||||
f.value = ref(1)
|
||||
})
|
||||
|
||||
// computed
|
||||
describe('allow computed getter and setter types to be unrelated', () => {
|
||||
const obj = ref({
|
||||
name: 'foo',
|
||||
})
|
||||
|
||||
const c = computed({
|
||||
get() {
|
||||
return JSON.stringify(obj.value)
|
||||
},
|
||||
set(val: typeof obj.value) {
|
||||
obj.value = val
|
||||
},
|
||||
})
|
||||
|
||||
c.value = { name: 'bar' } // object
|
||||
|
||||
expectType<string>(c.value)
|
||||
})
|
||||
|
||||
describe('Type safety for `WritableComputedRef` and `ComputedRef`', () => {
|
||||
// @ts-expect-error
|
||||
const writableComputed: WritableComputedRef<string> = computed(() => '')
|
||||
// should allow
|
||||
const immutableComputed: ComputedRef<string> = writableComputed
|
||||
expectType<ComputedRef<string>>(immutableComputed)
|
||||
})
|
||||
|
||||
// shallowRef
|
||||
type Status = 'initial' | 'ready' | 'invalidating'
|
||||
const shallowStatus = shallowRef<Status>('initial')
|
||||
if (shallowStatus.value === 'initial') {
|
||||
expectType<Ref<Status>>(shallowStatus)
|
||||
expectType<Status>(shallowStatus.value)
|
||||
shallowStatus.value = 'invalidating'
|
||||
}
|
||||
|
||||
const refStatus = ref<Status>('initial')
|
||||
if (refStatus.value === 'initial') {
|
||||
expectType<Ref<Status>>(shallowStatus)
|
||||
expectType<Status>(shallowStatus.value)
|
||||
refStatus.value = 'invalidating'
|
||||
}
|
||||
|
||||
{
|
||||
const shallow = shallowRef(1)
|
||||
expectType<Ref<number>>(shallow)
|
||||
expectType<ShallowRef<number>>(shallow)
|
||||
}
|
||||
|
||||
{
|
||||
//#7852
|
||||
type Steps = { step: '1' } | { step: '2' }
|
||||
const shallowUnionGenParam = shallowRef<Steps>({ step: '1' })
|
||||
const shallowUnionAsCast = shallowRef({ step: '1' } as Steps)
|
||||
|
||||
expectType<IsUnion<typeof shallowUnionGenParam>>(false)
|
||||
expectType<IsUnion<typeof shallowUnionAsCast>>(false)
|
||||
}
|
||||
|
||||
{
|
||||
// any value should return Ref<any>, not any
|
||||
const a = shallowRef(1 as any)
|
||||
expectType<IsAny<typeof a>>(false)
|
||||
}
|
||||
|
||||
describe('shallowRef with generic', <T extends { name: string }>() => {
|
||||
const r = {} as T
|
||||
const s = shallowRef(r)
|
||||
expectType<string>(s.value.name)
|
||||
expectType<ShallowRef<T>>(shallowRef(r))
|
||||
|
||||
const rr = {} as MaybeRef<T>
|
||||
// should at least allow casting
|
||||
const ss = shallowRef(rr) as Ref<T> | ShallowRef<T>
|
||||
expectType<string>(ss.value.name)
|
||||
})
|
||||
|
||||
{
|
||||
// should return ShallowRef<T> | Ref<T>, not ShallowRef<T | Ref<T>>
|
||||
expectType<ShallowRef<{ name: string }> | Ref<{ name: string }>>(
|
||||
shallowRef({} as MaybeRef<{ name: string }>),
|
||||
)
|
||||
expectType<ShallowRef<number> | Ref<string[]> | ShallowRef<string>>(
|
||||
shallowRef('' as Ref<string[]> | string | number),
|
||||
)
|
||||
}
|
||||
|
||||
// proxyRefs: should return `reactive` directly
|
||||
const r1 = reactive({
|
||||
k: 'v',
|
||||
})
|
||||
const p1 = proxyRefs(r1)
|
||||
expectType<typeof r1>(p1)
|
||||
|
||||
// proxyRefs: `ShallowUnwrapRef`
|
||||
const r2 = {
|
||||
a: ref(1),
|
||||
c: computed(() => 1),
|
||||
u: undefined,
|
||||
obj: {
|
||||
k: ref('foo'),
|
||||
},
|
||||
union: Math.random() > 0 - 5 ? ref({ name: 'yo' }) : null,
|
||||
}
|
||||
const p2 = proxyRefs(r2)
|
||||
expectType<number>(p2.a)
|
||||
expectType<number>(p2.c)
|
||||
expectType<undefined>(p2.u)
|
||||
expectType<Ref<string>>(p2.obj.k)
|
||||
expectType<{ name: string } | null>(p2.union)
|
||||
|
||||
// toRef and toRefs
|
||||
{
|
||||
const obj: {
|
||||
a: number
|
||||
b: Ref<number>
|
||||
c: number | string
|
||||
} = {
|
||||
a: 1,
|
||||
b: ref(1),
|
||||
c: 1,
|
||||
}
|
||||
|
||||
// toRef
|
||||
expectType<Ref<number>>(toRef(obj, 'a'))
|
||||
expectType<Ref<number>>(toRef(obj, 'b'))
|
||||
// Should not distribute Refs over union
|
||||
expectType<Ref<number | string>>(toRef(obj, 'c'))
|
||||
|
||||
expectType<Ref<number>>(toRef(() => 123))
|
||||
expectType<Ref<number | string>>(toRef(() => obj.c))
|
||||
|
||||
const r = toRef(() => 123)
|
||||
// @ts-expect-error
|
||||
r.value = 234
|
||||
|
||||
// toRefs
|
||||
expectType<{
|
||||
a: Ref<number>
|
||||
b: Ref<number>
|
||||
// Should not distribute Refs over union
|
||||
c: Ref<number | string>
|
||||
}>(toRefs(obj))
|
||||
|
||||
// Both should not do any unwrapping
|
||||
const someReactive = shallowReactive({
|
||||
a: {
|
||||
b: ref(42),
|
||||
},
|
||||
})
|
||||
|
||||
const toRefResult = toRef(someReactive, 'a')
|
||||
const toRefsResult = toRefs(someReactive)
|
||||
|
||||
expectType<Ref<number>>(toRefResult.value.b)
|
||||
expectType<Ref<number>>(toRefsResult.a.value.b)
|
||||
|
||||
// #5188
|
||||
const props = { foo: 1 } as { foo: any }
|
||||
const { foo } = toRefs(props)
|
||||
expectType<Ref<any>>(foo)
|
||||
}
|
||||
|
||||
// toRef default value
|
||||
{
|
||||
const obj: { x?: number } = {}
|
||||
const x = toRef(obj, 'x', 1)
|
||||
expectType<Ref<number>>(x)
|
||||
}
|
||||
|
||||
// readonly() + ref()
|
||||
expectType<Readonly<Ref<number>>>(readonly(ref(1)))
|
||||
|
||||
// #2687
|
||||
interface AppData {
|
||||
state: 'state1' | 'state2' | 'state3'
|
||||
}
|
||||
|
||||
const data: ToRefs<AppData> = toRefs(
|
||||
reactive({
|
||||
state: 'state1',
|
||||
}),
|
||||
)
|
||||
|
||||
switch (data.state.value) {
|
||||
case 'state1':
|
||||
data.state.value = 'state2'
|
||||
break
|
||||
case 'state2':
|
||||
data.state.value = 'state3'
|
||||
break
|
||||
case 'state3':
|
||||
data.state.value = 'state1'
|
||||
break
|
||||
}
|
||||
|
||||
// #3954
|
||||
function testUnrefGenerics<T>(p: T | Ref<T>) {
|
||||
expectType<T>(unref(p))
|
||||
}
|
||||
|
||||
testUnrefGenerics(1)
|
||||
|
||||
// #4771
|
||||
describe('shallow reactive in reactive', () => {
|
||||
const baz = reactive({
|
||||
foo: shallowReactive({
|
||||
a: {
|
||||
b: ref(42),
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
const foo = toRef(baz, 'foo')
|
||||
|
||||
expectType<Ref<number>>(foo.value.a.b)
|
||||
expectType<number>(foo.value.a.b.value)
|
||||
})
|
||||
|
||||
describe('shallow ref in reactive', () => {
|
||||
const x = reactive({
|
||||
foo: shallowRef({
|
||||
bar: {
|
||||
baz: ref(123),
|
||||
qux: reactive({
|
||||
z: ref(123),
|
||||
}),
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
expectType<Ref<number>>(x.foo.bar.baz)
|
||||
expectType<number>(x.foo.bar.qux.z)
|
||||
})
|
||||
|
||||
describe('ref in shallow ref', () => {
|
||||
const x = shallowRef({
|
||||
a: ref(123),
|
||||
})
|
||||
|
||||
expectType<Ref<number>>(x.value.a)
|
||||
})
|
||||
|
||||
describe('reactive in shallow ref', () => {
|
||||
const x = shallowRef({
|
||||
a: reactive({
|
||||
b: ref(0),
|
||||
}),
|
||||
})
|
||||
|
||||
expectType<number>(x.value.a.b)
|
||||
})
|
||||
|
||||
describe('toRef <-> toValue', () => {
|
||||
function foo(
|
||||
a: MaybeRef<string>,
|
||||
b: () => string,
|
||||
c: MaybeRefOrGetter<string>,
|
||||
d: ComputedRef<string>,
|
||||
) {
|
||||
const r = toRef(a)
|
||||
expectType<Ref<string>>(r)
|
||||
// writable
|
||||
r.value = 'foo'
|
||||
|
||||
const rb = toRef(b)
|
||||
expectType<Readonly<Ref<string>>>(rb)
|
||||
// @ts-expect-error ref created from getter should be readonly
|
||||
rb.value = 'foo'
|
||||
|
||||
const rc = toRef(c)
|
||||
expectType<Readonly<Ref<string> | Ref<string>>>(rc)
|
||||
// @ts-expect-error ref created from MaybeReadonlyRef should be readonly
|
||||
rc.value = 'foo'
|
||||
|
||||
const rd = toRef(d)
|
||||
expectType<ComputedRef<string>>(rd)
|
||||
// @ts-expect-error ref created from computed ref should be readonly
|
||||
rd.value = 'foo'
|
||||
|
||||
expectType<string>(toValue(a))
|
||||
expectType<string>(toValue(b))
|
||||
expectType<string>(toValue(c))
|
||||
expectType<string>(toValue(d))
|
||||
|
||||
return {
|
||||
r: toValue(r),
|
||||
rb: toValue(rb),
|
||||
rc: toValue(rc),
|
||||
rd: toValue(rd),
|
||||
}
|
||||
}
|
||||
|
||||
expectType<{
|
||||
r: string
|
||||
rb: string
|
||||
rc: string
|
||||
rd: string
|
||||
}>(
|
||||
foo(
|
||||
'foo',
|
||||
() => 'bar',
|
||||
ref('baz'),
|
||||
computed(() => 'hi'),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
// unref
|
||||
// #8747
|
||||
declare const unref1: number | Ref<number> | ComputedRef<number>
|
||||
expectType<number>(unref(unref1))
|
||||
|
||||
// #11356
|
||||
declare const unref2:
|
||||
| MaybeRef<string>
|
||||
| ShallowRef<string>
|
||||
| ComputedRef<string>
|
||||
| WritableComputedRef<string>
|
||||
expectType<string>(unref(unref2))
|
||||
|
||||
// toValue
|
||||
expectType<number>(toValue(unref1))
|
||||
expectType<string>(toValue(unref2))
|
||||
|
||||
// useTemplateRef
|
||||
const tRef = useTemplateRef('foo')
|
||||
expectType<Readonly<ShallowRef<unknown>>>(tRef)
|
||||
|
||||
const tRef2 = useTemplateRef<HTMLElement>('bar')
|
||||
expectType<Readonly<ShallowRef<HTMLElement | null>>>(tRef2)
|
|
@ -0,0 +1,609 @@
|
|||
import {
|
||||
type Ref,
|
||||
type Slots,
|
||||
type VNode,
|
||||
defineComponent,
|
||||
defineEmits,
|
||||
defineModel,
|
||||
defineOptions,
|
||||
defineProps,
|
||||
defineSlots,
|
||||
toRefs,
|
||||
useAttrs,
|
||||
useModel,
|
||||
useSlots,
|
||||
withDefaults,
|
||||
} from 'vue'
|
||||
import { describe, expectType } from './utils'
|
||||
|
||||
describe('defineProps w/ type declaration', () => {
|
||||
// type declaration
|
||||
const props = defineProps<{
|
||||
foo: string
|
||||
bool?: boolean
|
||||
boolAndUndefined: boolean | undefined
|
||||
file?: File | File[]
|
||||
}>()
|
||||
// explicitly declared type should be refined
|
||||
expectType<string>(props.foo)
|
||||
// @ts-expect-error
|
||||
props.bar
|
||||
|
||||
expectType<boolean>(props.bool)
|
||||
expectType<boolean>(props.boolAndUndefined)
|
||||
})
|
||||
|
||||
describe('defineProps w/ generics', () => {
|
||||
function test<T extends boolean>() {
|
||||
const props = defineProps<{ foo: T; bar: string; x?: boolean }>()
|
||||
expectType<T>(props.foo)
|
||||
expectType<string>(props.bar)
|
||||
expectType<boolean>(props.x)
|
||||
}
|
||||
test()
|
||||
})
|
||||
|
||||
describe('defineProps w/ type declaration + withDefaults', <T extends
|
||||
string>() => {
|
||||
const res = withDefaults(
|
||||
defineProps<{
|
||||
number?: number
|
||||
arr?: string[]
|
||||
obj?: { x: number }
|
||||
fn?: (e: string) => void
|
||||
genStr?: string
|
||||
x?: string
|
||||
y?: string
|
||||
z?: string
|
||||
bool?: boolean
|
||||
boolAndUndefined: boolean | undefined
|
||||
foo?: T
|
||||
}>(),
|
||||
{
|
||||
number: 123,
|
||||
arr: () => [],
|
||||
obj: () => ({ x: 123 }),
|
||||
fn: () => {},
|
||||
genStr: () => '',
|
||||
y: undefined,
|
||||
z: 'string',
|
||||
foo: '' as any,
|
||||
},
|
||||
)
|
||||
|
||||
res.number + 1
|
||||
res.arr.push('hi')
|
||||
res.obj.x
|
||||
res.fn('hi')
|
||||
res.genStr.slice()
|
||||
// @ts-expect-error
|
||||
res.x.slice()
|
||||
// @ts-expect-error
|
||||
res.y.slice()
|
||||
|
||||
expectType<string | undefined>(res.x)
|
||||
expectType<string | undefined>(res.y)
|
||||
expectType<string>(res.z)
|
||||
expectType<T>(res.foo)
|
||||
|
||||
expectType<boolean>(res.bool)
|
||||
expectType<boolean>(res.boolAndUndefined)
|
||||
})
|
||||
|
||||
describe('defineProps w/ union type declaration + withDefaults', () => {
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
union1?: number | number[] | { x: number }
|
||||
union2?: number | number[] | { x: number }
|
||||
union3?: number | number[] | { x: number }
|
||||
union4?: number | number[] | { x: number }
|
||||
}>(),
|
||||
{
|
||||
union1: 123,
|
||||
union2: () => [123],
|
||||
union3: () => ({ x: 123 }),
|
||||
union4: () => 123,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
describe('defineProps w/ object union + withDefaults', () => {
|
||||
const props = withDefaults(
|
||||
defineProps<
|
||||
{
|
||||
foo: string
|
||||
} & (
|
||||
| {
|
||||
type: 'hello'
|
||||
bar: string
|
||||
}
|
||||
| {
|
||||
type: 'world'
|
||||
bar: number
|
||||
}
|
||||
)
|
||||
>(),
|
||||
{
|
||||
foo: 'default value!',
|
||||
},
|
||||
)
|
||||
|
||||
expectType<
|
||||
| {
|
||||
readonly type: 'hello'
|
||||
readonly bar: string
|
||||
readonly foo: string
|
||||
}
|
||||
| {
|
||||
readonly type: 'world'
|
||||
readonly bar: number
|
||||
readonly foo: string
|
||||
}
|
||||
>(props)
|
||||
})
|
||||
|
||||
describe('defineProps w/ generic discriminate union + withDefaults', () => {
|
||||
interface B {
|
||||
b?: string
|
||||
}
|
||||
interface S<T> extends B {
|
||||
mode: 'single'
|
||||
v: T
|
||||
}
|
||||
interface M<T> extends B {
|
||||
mode: 'multiple'
|
||||
v: T[]
|
||||
}
|
||||
type Props = S<string> | M<string>
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
b: 'b',
|
||||
})
|
||||
|
||||
if (props.mode === 'single') {
|
||||
expectType<string>(props.v)
|
||||
}
|
||||
if (props.mode === 'multiple') {
|
||||
expectType<string[]>(props.v)
|
||||
}
|
||||
})
|
||||
|
||||
describe('defineProps w/ generic type declaration + withDefaults', <T extends
|
||||
number, TA extends {
|
||||
a: string
|
||||
}, TString extends string>() => {
|
||||
const res = withDefaults(
|
||||
defineProps<{
|
||||
n?: number
|
||||
bool?: boolean
|
||||
s?: string
|
||||
|
||||
generic1?: T[] | { x: T }
|
||||
generic2?: { x: T }
|
||||
generic3?: TString
|
||||
generic4?: TA
|
||||
}>(),
|
||||
{
|
||||
n: 123,
|
||||
|
||||
generic1: () => [123, 33] as T[],
|
||||
generic2: () => ({ x: 123 }) as { x: T },
|
||||
|
||||
generic3: () => 'test' as TString,
|
||||
generic4: () => ({ a: 'test' }) as TA,
|
||||
},
|
||||
)
|
||||
|
||||
res.n + 1
|
||||
// @ts-expect-error should be readonly
|
||||
res.n++
|
||||
// @ts-expect-error should be readonly
|
||||
res.s = ''
|
||||
|
||||
expectType<T[] | { x: T }>(res.generic1)
|
||||
expectType<{ x: T }>(res.generic2)
|
||||
expectType<TString>(res.generic3)
|
||||
expectType<TA>(res.generic4)
|
||||
|
||||
expectType<boolean>(res.bool)
|
||||
})
|
||||
|
||||
describe('withDefaults w/ boolean type', () => {
|
||||
const res1 = withDefaults(
|
||||
defineProps<{
|
||||
bool?: boolean
|
||||
}>(),
|
||||
{ bool: false },
|
||||
)
|
||||
expectType<boolean>(res1.bool)
|
||||
|
||||
const res2 = withDefaults(
|
||||
defineProps<{
|
||||
bool?: boolean
|
||||
}>(),
|
||||
{
|
||||
bool: undefined,
|
||||
},
|
||||
)
|
||||
expectType<boolean | undefined>(res2.bool)
|
||||
})
|
||||
|
||||
describe('withDefaults w/ defineProp type is different from the defaults type', () => {
|
||||
const res1 = withDefaults(
|
||||
defineProps<{
|
||||
bool?: boolean
|
||||
}>(),
|
||||
{ bool: false, value: false },
|
||||
)
|
||||
expectType<boolean>(res1.bool)
|
||||
|
||||
// @ts-expect-error
|
||||
res1.value
|
||||
})
|
||||
|
||||
describe('defineProps w/ runtime declaration', () => {
|
||||
// runtime declaration
|
||||
const props = defineProps({
|
||||
foo: String,
|
||||
bar: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
baz: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
expectType<{
|
||||
foo?: string
|
||||
bar: number
|
||||
baz: unknown[]
|
||||
}>(props)
|
||||
|
||||
props.foo && props.foo + 'bar'
|
||||
props.bar + 1
|
||||
// @ts-expect-error should be readonly
|
||||
props.bar++
|
||||
props.baz.push(1)
|
||||
|
||||
const props2 = defineProps(['foo', 'bar'])
|
||||
props2.foo + props2.bar
|
||||
// @ts-expect-error
|
||||
props2.baz
|
||||
})
|
||||
|
||||
describe('defineEmits w/ type declaration', () => {
|
||||
const emit = defineEmits<(e: 'change') => void>()
|
||||
emit('change')
|
||||
// @ts-expect-error
|
||||
emit()
|
||||
// @ts-expect-error
|
||||
emit('bar')
|
||||
|
||||
type Emits = { (e: 'foo' | 'bar'): void; (e: 'baz', id: number): void }
|
||||
const emit2 = defineEmits<Emits>()
|
||||
|
||||
emit2('foo')
|
||||
emit2('bar')
|
||||
emit2('baz', 123)
|
||||
// @ts-expect-error
|
||||
emit2('baz')
|
||||
})
|
||||
|
||||
describe('defineEmits w/ alt type declaration', () => {
|
||||
const emit = defineEmits<{
|
||||
foo: [id: string]
|
||||
bar: any[]
|
||||
baz: []
|
||||
}>()
|
||||
|
||||
emit('foo', 'hi')
|
||||
// @ts-expect-error
|
||||
emit('foo')
|
||||
|
||||
emit('bar')
|
||||
emit('bar', 1, 2, 3)
|
||||
|
||||
emit('baz')
|
||||
// @ts-expect-error
|
||||
emit('baz', 1)
|
||||
})
|
||||
|
||||
describe('defineEmits w/ runtime declaration', () => {
|
||||
const emit = defineEmits({
|
||||
foo: () => {},
|
||||
bar: null,
|
||||
})
|
||||
emit('foo')
|
||||
emit('bar', 123)
|
||||
// @ts-expect-error
|
||||
emit('baz')
|
||||
|
||||
const emit2 = defineEmits(['foo', 'bar'])
|
||||
emit2('foo')
|
||||
emit2('bar', 123)
|
||||
// @ts-expect-error
|
||||
emit2('baz')
|
||||
})
|
||||
|
||||
describe('defineSlots', () => {
|
||||
// literal fn syntax (allow for specifying return type)
|
||||
const fnSlots = defineSlots<{
|
||||
default(props: { foo: string; bar: number }): any
|
||||
optional?(props: string): any
|
||||
}>()
|
||||
expectType<(scope: { foo: string; bar: number }) => VNode[]>(fnSlots.default)
|
||||
expectType<undefined | ((scope: string) => VNode[])>(fnSlots.optional)
|
||||
|
||||
const slotsUntype = defineSlots()
|
||||
expectType<Slots>(slotsUntype)
|
||||
})
|
||||
|
||||
describe('defineSlots generic', <T extends Record<string, any>>() => {
|
||||
const props = defineProps<{
|
||||
item: T
|
||||
}>()
|
||||
|
||||
const slots = defineSlots<
|
||||
{
|
||||
[K in keyof T as `slot-${K & string}`]?: (props: { item: T }) => any
|
||||
} & {
|
||||
label?: (props: { item: T }) => any
|
||||
}
|
||||
>()
|
||||
|
||||
for (const key of Object.keys(props.item) as (keyof T & string)[]) {
|
||||
slots[`slot-${String(key)}`]?.({
|
||||
item: props.item,
|
||||
})
|
||||
}
|
||||
slots.label?.({ item: props.item })
|
||||
|
||||
// @ts-expect-error calling wrong slot
|
||||
slots.foo({})
|
||||
})
|
||||
|
||||
describe('defineModel', () => {
|
||||
// overload 1
|
||||
const modelValueRequired = defineModel<boolean>({ required: true })
|
||||
expectType<Ref<boolean>>(modelValueRequired)
|
||||
|
||||
// overload 2
|
||||
const modelValue = defineModel<string>()
|
||||
expectType<Ref<string | undefined>>(modelValue)
|
||||
modelValue.value = 'new value'
|
||||
|
||||
const modelValueDefault = defineModel<boolean>({ default: true })
|
||||
expectType<Ref<boolean>>(modelValueDefault)
|
||||
|
||||
// overload 3
|
||||
const countRequired = defineModel<number>('count', { required: false })
|
||||
expectType<Ref<number | undefined>>(countRequired)
|
||||
|
||||
// overload 4
|
||||
const count = defineModel<number>('count')
|
||||
expectType<Ref<number | undefined>>(count)
|
||||
|
||||
const countDefault = defineModel<number>('count', { default: 1 })
|
||||
expectType<Ref<number>>(countDefault)
|
||||
|
||||
// infer type from default
|
||||
const inferred = defineModel({ default: 123 })
|
||||
expectType<Ref<number | undefined>>(inferred)
|
||||
const inferredRequired = defineModel({ default: 123, required: true })
|
||||
expectType<Ref<number>>(inferredRequired)
|
||||
|
||||
// modifiers
|
||||
const [_, modifiers] = defineModel<string>()
|
||||
expectType<true | undefined>(modifiers.foo)
|
||||
|
||||
// limit supported modifiers
|
||||
const [__, typedModifiers] = defineModel<string, 'trim' | 'capitalize'>()
|
||||
expectType<true | undefined>(typedModifiers.trim)
|
||||
expectType<true | undefined>(typedModifiers.capitalize)
|
||||
// @ts-expect-error
|
||||
typedModifiers.foo
|
||||
|
||||
// transformers with type
|
||||
defineModel<string>({
|
||||
get(val) {
|
||||
return val.toLowerCase()
|
||||
},
|
||||
set(val) {
|
||||
return val.toUpperCase()
|
||||
},
|
||||
})
|
||||
// transformers with runtime type
|
||||
defineModel({
|
||||
type: String,
|
||||
get(val) {
|
||||
return val.toLowerCase()
|
||||
},
|
||||
set(val) {
|
||||
return val.toUpperCase()
|
||||
},
|
||||
})
|
||||
|
||||
// @ts-expect-error type / default mismatch
|
||||
defineModel<string>({ default: 123 })
|
||||
// @ts-expect-error unknown props option
|
||||
defineModel({ foo: 123 })
|
||||
|
||||
// unrelated getter and setter types
|
||||
{
|
||||
const modelVal = defineModel({
|
||||
get(_: string[]): string {
|
||||
return ''
|
||||
},
|
||||
set(_: number) {
|
||||
return 1
|
||||
},
|
||||
})
|
||||
expectType<string | undefined>(modelVal.value)
|
||||
modelVal.value = 1
|
||||
modelVal.value = undefined
|
||||
// @ts-expect-error
|
||||
modelVal.value = 'foo'
|
||||
|
||||
const [modelVal2] = modelVal
|
||||
expectType<string | undefined>(modelVal2.value)
|
||||
modelVal2.value = 1
|
||||
modelVal2.value = undefined
|
||||
// @ts-expect-error
|
||||
modelVal.value = 'foo'
|
||||
|
||||
const count = defineModel('count', {
|
||||
get(_: string[]): string {
|
||||
return ''
|
||||
},
|
||||
set(_: number) {
|
||||
return ''
|
||||
},
|
||||
})
|
||||
expectType<string | undefined>(count.value)
|
||||
count.value = 1
|
||||
count.value = undefined
|
||||
// @ts-expect-error
|
||||
count.value = 'foo'
|
||||
|
||||
const [count2] = count
|
||||
expectType<string | undefined>(count2.value)
|
||||
count2.value = 1
|
||||
count2.value = undefined
|
||||
// @ts-expect-error
|
||||
count2.value = 'foo'
|
||||
}
|
||||
})
|
||||
|
||||
describe('useModel', () => {
|
||||
defineComponent({
|
||||
props: ['foo'],
|
||||
setup(props) {
|
||||
const r = useModel(props, 'foo')
|
||||
expectType<Ref<any>>(r)
|
||||
|
||||
// @ts-expect-error
|
||||
useModel(props, 'bar')
|
||||
},
|
||||
})
|
||||
|
||||
defineComponent({
|
||||
props: {
|
||||
foo: String,
|
||||
bar: { type: Number, required: true },
|
||||
baz: { type: Boolean },
|
||||
},
|
||||
setup(props) {
|
||||
expectType<Ref<string | undefined>>(useModel(props, 'foo'))
|
||||
expectType<Ref<number>>(useModel(props, 'bar'))
|
||||
expectType<Ref<boolean>>(useModel(props, 'baz'))
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('useAttrs', () => {
|
||||
const attrs = useAttrs()
|
||||
expectType<Record<string, unknown>>(attrs)
|
||||
})
|
||||
|
||||
describe('useSlots', () => {
|
||||
const slots = useSlots()
|
||||
expectType<Slots>(slots)
|
||||
})
|
||||
|
||||
describe('defineSlots generic', <T extends Record<string, any>>() => {
|
||||
const props = defineProps<{
|
||||
item: T
|
||||
}>()
|
||||
|
||||
const slots = defineSlots<
|
||||
{
|
||||
[K in keyof T as `slot-${K & string}`]?: (props: { item: T }) => any
|
||||
} & {
|
||||
label?: (props: { item: T }) => any
|
||||
}
|
||||
>()
|
||||
|
||||
// @ts-expect-error slots should be readonly
|
||||
slots.label = () => {}
|
||||
|
||||
// @ts-expect-error non existing slot
|
||||
slots['foo-asdas']?.({
|
||||
item: props.item,
|
||||
})
|
||||
for (const key in props.item) {
|
||||
slots[`slot-${String(key)}`]?.({
|
||||
item: props.item,
|
||||
})
|
||||
slots[`slot-${String(key as keyof T)}`]?.({
|
||||
item: props.item,
|
||||
})
|
||||
}
|
||||
|
||||
for (const key of Object.keys(props.item) as (keyof T)[]) {
|
||||
slots[`slot-${String(key)}`]?.({
|
||||
item: props.item,
|
||||
})
|
||||
}
|
||||
slots.label?.({ item: props.item })
|
||||
|
||||
// @ts-expect-error calling wrong slot
|
||||
slots.foo({})
|
||||
})
|
||||
|
||||
describe('defineSlots generic strict', <T extends {
|
||||
foo: 'foo'
|
||||
bar: 'bar'
|
||||
}>() => {
|
||||
const props = defineProps<{
|
||||
item: T
|
||||
}>()
|
||||
|
||||
const slots = defineSlots<
|
||||
{
|
||||
[K in keyof T as `slot-${K & string}`]?: (props: { item: T }) => any
|
||||
} & {
|
||||
label?: (props: { item: T }) => any
|
||||
}
|
||||
>()
|
||||
|
||||
// slot-bar/foo should be automatically inferred
|
||||
slots['slot-bar']?.({ item: props.item })
|
||||
slots['slot-foo']?.({ item: props.item })
|
||||
|
||||
slots.label?.({ item: props.item })
|
||||
|
||||
// @ts-expect-error not part of the extends
|
||||
slots['slot-RANDOM']?.({ item: props.item })
|
||||
|
||||
// @ts-expect-error slots should be readonly
|
||||
slots.label = () => {}
|
||||
|
||||
// @ts-expect-error calling wrong slot
|
||||
slots.foo({})
|
||||
})
|
||||
|
||||
// #6420
|
||||
describe('toRefs w/ type declaration', () => {
|
||||
const props = defineProps<{
|
||||
file?: File | File[]
|
||||
}>()
|
||||
expectType<Ref<File | File[] | undefined>>(toRefs(props).file)
|
||||
})
|
||||
|
||||
describe('defineOptions', () => {
|
||||
defineOptions({
|
||||
name: 'MyComponent',
|
||||
inheritAttrs: true,
|
||||
})
|
||||
|
||||
defineOptions({
|
||||
// @ts-expect-error props should be defined via defineProps()
|
||||
props: ['props'],
|
||||
// @ts-expect-error emits should be defined via defineEmits()
|
||||
emits: ['emits'],
|
||||
// @ts-expect-error slots should be defined via defineSlots()
|
||||
slots: { default: 'default' },
|
||||
// @ts-expect-error expose should be defined via defineExpose()
|
||||
expose: ['expose'],
|
||||
})
|
||||
})
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"moduleResolution": "node",
|
||||
"lib": ["esnext", "dom"]
|
||||
},
|
||||
"include": ["./*"]
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
// TSX w/ defineComponent is tested in defineComponent.test-d.tsx
|
||||
import { Fragment, KeepAlive, Suspense, Teleport, type VNode } from 'vue'
|
||||
import { expectType } from './utils'
|
||||
|
||||
expectType<VNode>(<div />)
|
||||
expectType<JSX.Element>(<div />)
|
||||
expectType<JSX.Element>(<div id="foo" />)
|
||||
expectType<JSX.Element>(<div>hello</div>)
|
||||
expectType<JSX.Element>(<input value="foo" />)
|
||||
expectType<JSX.Element>(<textarea value={null} />)
|
||||
|
||||
// @ts-expect-error style css property validation
|
||||
;<div style={{ unknown: 123 }} />
|
||||
|
||||
// allow array styles and nested array styles
|
||||
expectType<JSX.Element>(<div style={[{ color: 'red' }]} />)
|
||||
expectType<JSX.Element>(
|
||||
<div style={[{ color: 'red' }, [{ fontSize: '1em' }]]} />,
|
||||
)
|
||||
|
||||
// allow undefined, string, object, array and nested array classes
|
||||
expectType<JSX.Element>(<div class={undefined} />)
|
||||
expectType<JSX.Element>(<div class={'foo'} />)
|
||||
expectType<JSX.Element>(<div class={['foo', undefined, 'bar']} />)
|
||||
expectType<JSX.Element>(<div class={[]} />)
|
||||
expectType<JSX.Element>(<div class={['foo', ['bar'], [['baz']]]} />)
|
||||
expectType<JSX.Element>(<div class={{ foo: true, bar: false, baz: true }} />)
|
||||
expectType<JSX.Element>(<div class={{}} />)
|
||||
expectType<JSX.Element>(
|
||||
<div class={['foo', ['bar'], { baz: true }, [{ qux: true }]]} />,
|
||||
)
|
||||
expectType<JSX.Element>(
|
||||
<div
|
||||
class={[
|
||||
{ foo: false },
|
||||
{ bar: 0 },
|
||||
{ baz: -0 },
|
||||
{ qux: '' },
|
||||
{ quux: null },
|
||||
{ corge: undefined },
|
||||
{ grault: NaN },
|
||||
]}
|
||||
/>,
|
||||
)
|
||||
expectType<JSX.Element>(
|
||||
<div
|
||||
class={[
|
||||
{ foo: true },
|
||||
{ bar: 'not-empty' },
|
||||
{ baz: 1 },
|
||||
{ qux: {} },
|
||||
{ quux: [] },
|
||||
]}
|
||||
/>,
|
||||
)
|
||||
|
||||
// #7955
|
||||
expectType<JSX.Element>(<div style={[undefined, '', null, false]} />)
|
||||
|
||||
expectType<JSX.Element>(<div style={undefined} />)
|
||||
|
||||
expectType<JSX.Element>(<div style={null} />)
|
||||
|
||||
expectType<JSX.Element>(<div style={''} />)
|
||||
|
||||
expectType<JSX.Element>(<div style={false} />)
|
||||
|
||||
// @ts-expect-error
|
||||
;<div style={[0]} />
|
||||
|
||||
// @ts-expect-error
|
||||
;<div style={0} />
|
||||
|
||||
// @ts-expect-error unknown prop
|
||||
;<div foo="bar" />
|
||||
|
||||
// allow key/ref on arbitrary element
|
||||
expectType<JSX.Element>(<div key="foo" />)
|
||||
expectType<JSX.Element>(<div ref="bar" />)
|
||||
|
||||
expectType<JSX.Element>(
|
||||
<input
|
||||
onInput={e => {
|
||||
// infer correct event type
|
||||
expectType<EventTarget | null>(e.target)
|
||||
}}
|
||||
/>,
|
||||
)
|
||||
|
||||
// built-in types
|
||||
expectType<JSX.Element>(<Fragment />)
|
||||
expectType<JSX.Element>(<Fragment key="1" />)
|
||||
|
||||
expectType<JSX.Element>(<Teleport to="#foo" />)
|
||||
expectType<JSX.Element>(<Teleport to="#foo" key="1" />)
|
||||
|
||||
// @ts-expect-error
|
||||
;<Teleport />
|
||||
// @ts-expect-error
|
||||
;<Teleport to={1} />
|
||||
|
||||
// KeepAlive
|
||||
expectType<JSX.Element>(<KeepAlive include="foo" exclude={['a']} />)
|
||||
expectType<JSX.Element>(<KeepAlive key="1" />)
|
||||
// @ts-expect-error
|
||||
;<KeepAlive include={123} />
|
||||
|
||||
// Suspense
|
||||
expectType<JSX.Element>(<Suspense />)
|
||||
expectType<JSX.Element>(<Suspense key="1" />)
|
||||
expectType<JSX.Element>(
|
||||
<Suspense onResolve={() => {}} onFallback={() => {}} onPending={() => {}} />,
|
||||
)
|
||||
// @ts-expect-error
|
||||
;<Suspense onResolve={123} />
|
||||
|
||||
// svg
|
||||
expectType<JSX.Element>(
|
||||
<svg
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>,
|
||||
)
|
||||
// details
|
||||
expectType<JSX.Element>(<details name="details" />)
|
|
@ -0,0 +1,21 @@
|
|||
// This directory contains a number of d.ts assertions
|
||||
// use \@ts-expect-error where errors are expected.
|
||||
|
||||
// register global JSX
|
||||
import 'vue/jsx'
|
||||
|
||||
export function describe(_name: string, _fn: () => void): void
|
||||
export function test(_name: string, _fn: () => any): void
|
||||
|
||||
export function expectType<T>(value: T): void
|
||||
export function expectAssignable<T, T2 extends T = T>(value: T2): void
|
||||
|
||||
export type IsUnion<T, U extends T = T> = (
|
||||
T extends any ? (U extends T ? false : true) : never
|
||||
) extends false
|
||||
? false
|
||||
: true
|
||||
|
||||
export type IsAny<T> = 0 extends 1 & T ? true : false
|
||||
|
||||
export type Prettify<T> = { [K in keyof T]: T[K] } & {}
|
|
@ -0,0 +1,213 @@
|
|||
import {
|
||||
type ComputedRef,
|
||||
type MaybeRef,
|
||||
type Ref,
|
||||
computed,
|
||||
defineComponent,
|
||||
defineModel,
|
||||
reactive,
|
||||
ref,
|
||||
shallowRef,
|
||||
watch,
|
||||
} from 'vue'
|
||||
import { expectType } from './utils'
|
||||
|
||||
const source = ref('foo')
|
||||
const source2 = computed(() => source.value)
|
||||
const source3 = () => 1
|
||||
|
||||
type Bar = Ref<string> | ComputedRef<string> | (() => number)
|
||||
type Foo = readonly [Ref<string>, ComputedRef<string>, () => number]
|
||||
type OnCleanup = (fn: () => void) => void
|
||||
|
||||
const readonlyArr: Foo = [source, source2, source3]
|
||||
|
||||
// lazy watcher will have consistent types for oldValue.
|
||||
watch(source, (value, oldValue, onCleanup) => {
|
||||
expectType<string>(value)
|
||||
expectType<string>(oldValue)
|
||||
expectType<OnCleanup>(onCleanup)
|
||||
})
|
||||
|
||||
watch([source, source2, source3], (values, oldValues) => {
|
||||
expectType<[string, string, number]>(values)
|
||||
expectType<[string, string, number]>(oldValues)
|
||||
})
|
||||
|
||||
// const array
|
||||
watch([source, source2, source3] as const, (values, oldValues) => {
|
||||
expectType<Readonly<[string, string, number]>>(values)
|
||||
expectType<Readonly<[string, string, number]>>(oldValues)
|
||||
})
|
||||
|
||||
// reactive array
|
||||
watch(reactive([source, source2, source3]), (value, oldValues) => {
|
||||
expectType<Bar[]>(value)
|
||||
expectType<Bar[]>(oldValues)
|
||||
})
|
||||
|
||||
// reactive w/ readonly tuple
|
||||
watch(reactive([source, source2, source3] as const), (value, oldValues) => {
|
||||
expectType<Foo>(value)
|
||||
expectType<Foo>(oldValues)
|
||||
})
|
||||
|
||||
// readonly array
|
||||
watch(readonlyArr, (values, oldValues) => {
|
||||
expectType<Readonly<[string, string, number]>>(values)
|
||||
expectType<Readonly<[string, string, number]>>(oldValues)
|
||||
})
|
||||
|
||||
// no type error, case from vueuse
|
||||
declare const aAny: any
|
||||
watch(aAny, (v, ov) => {})
|
||||
watch(aAny, (v, ov) => {}, { immediate: true })
|
||||
|
||||
// immediate watcher's oldValue will be undefined on first run.
|
||||
watch(
|
||||
source,
|
||||
(value, oldValue) => {
|
||||
expectType<string>(value)
|
||||
expectType<string | undefined>(oldValue)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
watch(
|
||||
[source, source2, source3],
|
||||
(values, oldValues) => {
|
||||
expectType<[string, string, number]>(values)
|
||||
expectType<[string | undefined, string | undefined, number | undefined]>(
|
||||
oldValues,
|
||||
)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
// const array
|
||||
watch(
|
||||
[source, source2, source3] as const,
|
||||
(values, oldValues) => {
|
||||
expectType<Readonly<[string, string, number]>>(values)
|
||||
expectType<
|
||||
Readonly<[string | undefined, string | undefined, number | undefined]>
|
||||
>(oldValues)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
// reactive array
|
||||
watch(
|
||||
reactive([source, source2, source3]),
|
||||
(value, oldVals) => {
|
||||
expectType<Bar[]>(value)
|
||||
expectType<Bar[] | undefined>(oldVals)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
// reactive w/ readonly tuple
|
||||
watch(reactive([source, source2, source3] as const), (value, oldVals) => {
|
||||
expectType<Foo>(value)
|
||||
expectType<Foo | undefined>(oldVals)
|
||||
})
|
||||
|
||||
// readonly array
|
||||
watch(
|
||||
readonlyArr,
|
||||
(values, oldValues) => {
|
||||
expectType<Readonly<[string, string, number]>>(values)
|
||||
expectType<
|
||||
Readonly<[string | undefined, string | undefined, number | undefined]>
|
||||
>(oldValues)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
// should provide correct ref.value inner type to callbacks
|
||||
const nestedRefSource = ref({
|
||||
foo: ref(1),
|
||||
})
|
||||
|
||||
watch(nestedRefSource, (v, ov) => {
|
||||
expectType<{ foo: number }>(v)
|
||||
expectType<{ foo: number }>(ov)
|
||||
})
|
||||
|
||||
const someRef = ref({ test: 'test' })
|
||||
const otherRef = ref({ a: 'b' })
|
||||
watch([someRef, otherRef], values => {
|
||||
const value1 = values[0]
|
||||
// no type error
|
||||
console.log(value1.test)
|
||||
|
||||
const value2 = values[1]
|
||||
// no type error
|
||||
console.log(value2.a)
|
||||
})
|
||||
|
||||
// #6135
|
||||
defineComponent({
|
||||
data() {
|
||||
return { a: 1 }
|
||||
},
|
||||
created() {
|
||||
this.$watch(
|
||||
() => this.a,
|
||||
(v, ov, onCleanup) => {
|
||||
expectType<number>(v)
|
||||
expectType<number>(ov)
|
||||
expectType<OnCleanup>(onCleanup)
|
||||
},
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
{
|
||||
//#7852
|
||||
type Steps = { step: '1' } | { step: '2' }
|
||||
const shallowUnionGenParam = shallowRef<Steps>({ step: '1' })
|
||||
const shallowUnionAsCast = shallowRef({ step: '1' } as Steps)
|
||||
|
||||
watch(shallowUnionGenParam, value => {
|
||||
expectType<Steps>(value)
|
||||
})
|
||||
watch(shallowUnionAsCast, value => {
|
||||
expectType<Steps>(value)
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
// defineModel
|
||||
const bool = defineModel({ default: false })
|
||||
watch(bool, value => {
|
||||
expectType<boolean>(value)
|
||||
})
|
||||
|
||||
const bool1 = defineModel<boolean>()
|
||||
watch(bool1, value => {
|
||||
expectType<boolean | undefined>(value)
|
||||
})
|
||||
|
||||
const msg = defineModel<string>({ required: true })
|
||||
watch(msg, value => {
|
||||
expectType<string>(value)
|
||||
})
|
||||
|
||||
const arr = defineModel<string[]>({ required: true })
|
||||
watch(arr, value => {
|
||||
expectType<string[]>(value)
|
||||
})
|
||||
|
||||
const obj = defineModel<{ foo: string }>({ required: true })
|
||||
watch(obj, value => {
|
||||
expectType<{ foo: string }>(value)
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
const css: MaybeRef<string> = ''
|
||||
watch(ref(css), value => {
|
||||
expectType<string>(value)
|
||||
})
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
# SFC Playground
|
||||
|
||||
This is continuously deployed at [https://play.vuejs.org](https://play.vuejs.org).
|
||||
|
||||
## Run Locally in Dev
|
||||
|
||||
In repo root:
|
||||
|
||||
```sh
|
||||
pnpm dev-sfc
|
||||
```
|
||||
|
||||
## Build for Prod
|
||||
|
||||
In repo root
|
||||
|
||||
```sh
|
||||
pnpm build-sfc-playground
|
||||
```
|
|
@ -0,0 +1,26 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/svg" href="/logo.svg" />
|
||||
<title>Vue SFC Playground</title>
|
||||
<script>
|
||||
const savedPreferDark = localStorage.getItem(
|
||||
'vue-sfc-playground-prefer-dark',
|
||||
)
|
||||
if (
|
||||
savedPreferDark === 'true' ||
|
||||
(!savedPreferDark &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
document.documentElement.classList.add('dark')
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "@vue/sfc-playground",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "catalog:",
|
||||
"vite": "catalog:"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue/repl": "^4.3.1",
|
||||
"file-saver": "^2.0.5",
|
||||
"jszip": "^3.10.1",
|
||||
"vue": "workspace:*"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 261 B After Width: | Height: | Size: 261 B |
|
@ -0,0 +1,170 @@
|
|||
<script setup lang="ts">
|
||||
import Header from './Header.vue'
|
||||
import { Repl, useStore, SFCOptions, useVueImportMap } from '@vue/repl'
|
||||
import Monaco from '@vue/repl/monaco-editor'
|
||||
import { ref, watchEffect, onMounted, computed } from 'vue'
|
||||
|
||||
const replRef = ref<InstanceType<typeof Repl>>()
|
||||
|
||||
const setVH = () => {
|
||||
document.documentElement.style.setProperty('--vh', window.innerHeight + `px`)
|
||||
}
|
||||
window.addEventListener('resize', setVH)
|
||||
setVH()
|
||||
|
||||
const useSSRMode = ref(false)
|
||||
|
||||
const { productionMode, vueVersion, importMap } = useVueImportMap({
|
||||
runtimeDev: import.meta.env.PROD
|
||||
? `${location.origin}/vue.runtime.esm-browser.js`
|
||||
: `${location.origin}/src/vue-dev-proxy`,
|
||||
runtimeProd: import.meta.env.PROD
|
||||
? `${location.origin}/vue.runtime.esm-browser.prod.js`
|
||||
: `${location.origin}/src/vue-dev-proxy-prod`,
|
||||
serverRenderer: import.meta.env.PROD
|
||||
? `${location.origin}/server-renderer.esm-browser.js`
|
||||
: `${location.origin}/src/vue-server-renderer-dev-proxy`,
|
||||
})
|
||||
|
||||
let hash = location.hash.slice(1)
|
||||
if (hash.startsWith('__DEV__')) {
|
||||
hash = hash.slice(7)
|
||||
productionMode.value = false
|
||||
}
|
||||
if (hash.startsWith('__PROD__')) {
|
||||
hash = hash.slice(8)
|
||||
productionMode.value = true
|
||||
}
|
||||
if (hash.startsWith('__SSR__')) {
|
||||
hash = hash.slice(7)
|
||||
useSSRMode.value = true
|
||||
}
|
||||
|
||||
// enable experimental features
|
||||
const sfcOptions = computed(
|
||||
(): SFCOptions => ({
|
||||
script: {
|
||||
inlineTemplate: productionMode.value,
|
||||
isProd: productionMode.value,
|
||||
propsDestructure: true,
|
||||
},
|
||||
style: {
|
||||
isProd: productionMode.value,
|
||||
},
|
||||
template: {
|
||||
isProd: productionMode.value,
|
||||
compilerOptions: {
|
||||
isCustomElement: (tag: string) =>
|
||||
tag === 'mjx-container' || tag.startsWith('custom-'),
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
const store = useStore(
|
||||
{
|
||||
builtinImportMap: importMap,
|
||||
vueVersion,
|
||||
sfcOptions,
|
||||
},
|
||||
hash,
|
||||
)
|
||||
// @ts-expect-error
|
||||
globalThis.store = store
|
||||
|
||||
// persist state
|
||||
watchEffect(() => {
|
||||
const newHash = store
|
||||
.serialize()
|
||||
.replace(/^#/, useSSRMode.value ? `#__SSR__` : `#`)
|
||||
.replace(/^#/, productionMode.value ? `#__PROD__` : `#`)
|
||||
history.replaceState({}, '', newHash)
|
||||
})
|
||||
|
||||
function toggleProdMode() {
|
||||
productionMode.value = !productionMode.value
|
||||
}
|
||||
|
||||
function toggleSSR() {
|
||||
useSSRMode.value = !useSSRMode.value
|
||||
}
|
||||
|
||||
function reloadPage() {
|
||||
replRef.value?.reload()
|
||||
}
|
||||
|
||||
const theme = ref<'dark' | 'light'>('dark')
|
||||
function toggleTheme(isDark: boolean) {
|
||||
theme.value = isDark ? 'dark' : 'light'
|
||||
}
|
||||
onMounted(() => {
|
||||
const cls = document.documentElement.classList
|
||||
toggleTheme(cls.contains('dark'))
|
||||
|
||||
// @ts-expect-error process shim for old versions of @vue/compiler-sfc dependency
|
||||
window.process = { env: {} }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Header
|
||||
:store="store"
|
||||
:prod="productionMode"
|
||||
:ssr="useSSRMode"
|
||||
@toggle-theme="toggleTheme"
|
||||
@toggle-prod="toggleProdMode"
|
||||
@toggle-ssr="toggleSSR"
|
||||
@reload-page="reloadPage"
|
||||
/>
|
||||
<Repl
|
||||
ref="replRef"
|
||||
:theme="theme"
|
||||
:editor="Monaco"
|
||||
@keydown.ctrl.s.prevent
|
||||
@keydown.meta.s.prevent
|
||||
:ssr="useSSRMode"
|
||||
:store="store"
|
||||
:showCompileOutput="true"
|
||||
:autoResize="true"
|
||||
:clearConsole="false"
|
||||
:preview-options="{
|
||||
customCode: {
|
||||
importCode: `import { initCustomFormatter } from 'vue'`,
|
||||
useCode: `if (window.devtoolsFormatters) {
|
||||
const index = window.devtoolsFormatters.findIndex((v) => v.__vue_custom_formatter)
|
||||
window.devtoolsFormatters.splice(index, 1)
|
||||
initCustomFormatter()
|
||||
} else {
|
||||
initCustomFormatter()
|
||||
}`,
|
||||
},
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.dark {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 13px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
margin: 0;
|
||||
--base: #444;
|
||||
--nav-height: 50px;
|
||||
}
|
||||
|
||||
.vue-repl {
|
||||
height: calc(var(--vh) - var(--nav-height)) !important;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,299 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { ReplStore } from '@vue/repl'
|
||||
import { downloadProject } from './download/download'
|
||||
import Sun from './icons/Sun.vue'
|
||||
import Moon from './icons/Moon.vue'
|
||||
import Share from './icons/Share.vue'
|
||||
import Download from './icons/Download.vue'
|
||||
import GitHub from './icons/GitHub.vue'
|
||||
import Reload from './icons/Reload.vue'
|
||||
import VersionSelect from './VersionSelect.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
store: ReplStore
|
||||
prod: boolean
|
||||
ssr: boolean
|
||||
}>()
|
||||
const emit = defineEmits([
|
||||
'toggle-theme',
|
||||
'toggle-ssr',
|
||||
'toggle-prod',
|
||||
'reload-page',
|
||||
])
|
||||
|
||||
const { store } = props
|
||||
|
||||
const currentCommit = __COMMIT__
|
||||
|
||||
const vueVersion = computed(() => {
|
||||
if (store.loading) {
|
||||
return 'loading...'
|
||||
}
|
||||
return store.vueVersion || `@${__COMMIT__}`
|
||||
})
|
||||
|
||||
async function setVueVersion(v: string) {
|
||||
store.vueVersion = v
|
||||
}
|
||||
|
||||
function resetVueVersion() {
|
||||
store.vueVersion = null
|
||||
}
|
||||
|
||||
async function copyLink(e: MouseEvent) {
|
||||
if (e.metaKey) {
|
||||
// hidden logic for going to local debug from play.vuejs.org
|
||||
window.location.href = 'http://localhost:5173/' + window.location.hash
|
||||
return
|
||||
}
|
||||
await navigator.clipboard.writeText(location.href)
|
||||
alert('Sharable URL has been copied to clipboard.')
|
||||
}
|
||||
|
||||
function toggleDark() {
|
||||
const cls = document.documentElement.classList
|
||||
cls.toggle('dark')
|
||||
localStorage.setItem(
|
||||
'vue-sfc-playground-prefer-dark',
|
||||
String(cls.contains('dark')),
|
||||
)
|
||||
emit('toggle-theme', cls.contains('dark'))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav>
|
||||
<h1>
|
||||
<img alt="logo" src="/logo.svg" />
|
||||
<span>Vue SFC Playground</span>
|
||||
</h1>
|
||||
<div class="links">
|
||||
<VersionSelect
|
||||
v-model="store.typescriptVersion"
|
||||
pkg="typescript"
|
||||
label="TypeScript Version"
|
||||
/>
|
||||
<VersionSelect
|
||||
:model-value="vueVersion"
|
||||
@update:model-value="setVueVersion"
|
||||
pkg="vue"
|
||||
label="Vue Version"
|
||||
>
|
||||
<li :class="{ active: vueVersion === `@${currentCommit}` }">
|
||||
<a @click="resetVueVersion">This Commit ({{ currentCommit }})</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://app.netlify.com/sites/vue-sfc-playground/deploys"
|
||||
target="_blank"
|
||||
>Commits History</a
|
||||
>
|
||||
</li>
|
||||
</VersionSelect>
|
||||
<button
|
||||
title="Toggle development production mode"
|
||||
class="toggle-prod"
|
||||
:class="{ prod }"
|
||||
@click="$emit('toggle-prod')"
|
||||
>
|
||||
<span>{{ prod ? 'PROD' : 'DEV' }}</span>
|
||||
</button>
|
||||
<button
|
||||
title="Toggle server rendering mode"
|
||||
class="toggle-ssr"
|
||||
:class="{ enabled: ssr }"
|
||||
@click="$emit('toggle-ssr')"
|
||||
>
|
||||
<span>{{ ssr ? 'SSR ON' : 'SSR OFF' }}</span>
|
||||
</button>
|
||||
<button title="Toggle dark mode" class="toggle-dark" @click="toggleDark">
|
||||
<Sun class="light" />
|
||||
<Moon class="dark" />
|
||||
</button>
|
||||
<button title="Copy sharable URL" class="share" @click="copyLink">
|
||||
<Share />
|
||||
</button>
|
||||
<button title="Reload page" class="reload" @click="$emit('reload-page')">
|
||||
<Reload />
|
||||
</button>
|
||||
<button
|
||||
title="Download project files"
|
||||
class="download"
|
||||
@click="downloadProject(store)"
|
||||
>
|
||||
<Download />
|
||||
</button>
|
||||
<a
|
||||
href="https://github.com/vuejs/core/tree/main/packages-private/sfc-playground"
|
||||
target="_blank"
|
||||
title="View on GitHub"
|
||||
class="github"
|
||||
>
|
||||
<GitHub />
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
--bg: #fff;
|
||||
--bg-light: #fff;
|
||||
--border: #ddd;
|
||||
--btn: #666;
|
||||
--highlight: #333;
|
||||
--green: #3ca877;
|
||||
--purple: #904cbc;
|
||||
--btn-bg: #eee;
|
||||
|
||||
color: var(--base);
|
||||
height: var(--nav-height);
|
||||
box-sizing: border-box;
|
||||
padding: 0 1em;
|
||||
background-color: var(--bg);
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.33);
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dark nav {
|
||||
--base: #ddd;
|
||||
--bg: #1a1a1a;
|
||||
--bg-light: #242424;
|
||||
--border: #383838;
|
||||
--highlight: #fff;
|
||||
--btn-bg: #333;
|
||||
|
||||
box-shadow: none;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
display: inline-flex;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
h1 img {
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
h1 span {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
h1 span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.links {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.toggle-prod span,
|
||||
.toggle-ssr span {
|
||||
font-size: 12px;
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
.toggle-prod span {
|
||||
background: var(--green);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.toggle-prod.prod span {
|
||||
background: var(--purple);
|
||||
}
|
||||
|
||||
.toggle-ssr span {
|
||||
background-color: var(--btn-bg);
|
||||
}
|
||||
|
||||
.toggle-ssr.enabled span {
|
||||
color: #fff;
|
||||
background-color: var(--green);
|
||||
}
|
||||
|
||||
.toggle-dark svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.toggle-dark .dark,
|
||||
.dark .toggle-dark .light {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dark .toggle-dark .dark {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.links button,
|
||||
.links .github {
|
||||
padding: 1px 6px;
|
||||
color: var(--btn);
|
||||
}
|
||||
|
||||
.links button:hover,
|
||||
.links .github:hover {
|
||||
color: var(--highlight);
|
||||
}
|
||||
|
||||
.version:hover .active-version::after {
|
||||
border-top-color: var(--btn);
|
||||
}
|
||||
|
||||
.dark .version:hover .active-version::after {
|
||||
border-top-color: var(--highlight);
|
||||
}
|
||||
|
||||
.versions {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 40px;
|
||||
background-color: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
list-style-type: none;
|
||||
padding: 8px;
|
||||
margin: 0;
|
||||
width: 200px;
|
||||
max-height: calc(100vh - 70px);
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.versions a {
|
||||
display: block;
|
||||
padding: 6px 12px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
color: var(--base);
|
||||
}
|
||||
|
||||
.versions a:hover {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.versions.expanded {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.links > * {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.links > * + * {
|
||||
margin-left: 4px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,151 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import Copy from './icons/Copy.vue'
|
||||
|
||||
const expanded = ref(false)
|
||||
const versions = ref<string[]>()
|
||||
|
||||
const version = defineModel()
|
||||
const props = defineProps<{
|
||||
pkg: string
|
||||
label: string
|
||||
}>()
|
||||
|
||||
async function toggle() {
|
||||
expanded.value = !expanded.value
|
||||
if (!versions.value) {
|
||||
versions.value = await fetchVersions()
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchVersions(): Promise<string[]> {
|
||||
const res = await fetch(
|
||||
`https://data.jsdelivr.com/v1/package/npm/${props.pkg}`,
|
||||
)
|
||||
const { versions } = (await res.json()) as { versions: string[] }
|
||||
|
||||
if (props.pkg === 'vue') {
|
||||
// if the latest version is a pre-release, list all current pre-releases
|
||||
// otherwise filter out pre-releases
|
||||
let isInPreRelease = versions[0].includes('-')
|
||||
const filteredVersions: string[] = []
|
||||
for (const v of versions) {
|
||||
if (v.includes('-')) {
|
||||
if (isInPreRelease) {
|
||||
filteredVersions.push(v)
|
||||
}
|
||||
} else {
|
||||
filteredVersions.push(v)
|
||||
isInPreRelease = false
|
||||
}
|
||||
if (filteredVersions.length >= 30 || v === '3.0.10') {
|
||||
break
|
||||
}
|
||||
}
|
||||
return filteredVersions
|
||||
} else if (props.pkg === 'typescript') {
|
||||
return versions.filter(v => !v.includes('dev') && !v.includes('insiders'))
|
||||
}
|
||||
return versions
|
||||
}
|
||||
|
||||
function setVersion(v: string) {
|
||||
version.value = v
|
||||
expanded.value = false
|
||||
}
|
||||
|
||||
function copyVersion(v: string) {
|
||||
window.navigator.clipboard.writeText(v).then(() => {
|
||||
alert('Vue version has been copied to clipboard.')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('click', () => {
|
||||
expanded.value = false
|
||||
})
|
||||
window.addEventListener('blur', () => {
|
||||
if (document.activeElement?.tagName === 'IFRAME') {
|
||||
expanded.value = false
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="version" @click.stop>
|
||||
<span class="active-version" @click="toggle">
|
||||
{{ label }}
|
||||
<span class="number">{{ version }}</span>
|
||||
</span>
|
||||
|
||||
<ul class="versions" :class="{ expanded }">
|
||||
<li v-if="!versions"><a>loading versions...</a></li>
|
||||
<li
|
||||
v-for="(ver, index) of versions"
|
||||
class="versions-item"
|
||||
:class="{
|
||||
active: ver === version || (version === 'latest' && index === 0),
|
||||
}"
|
||||
>
|
||||
<a @click="setVersion(ver)">v{{ ver }}</a>
|
||||
<button
|
||||
title="Copy Version"
|
||||
class="version-copy"
|
||||
@click="copyVersion(`v${ver}`)"
|
||||
>
|
||||
<Copy />
|
||||
</button>
|
||||
</li>
|
||||
<div @click="expanded = false">
|
||||
<slot />
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.version {
|
||||
margin-right: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.active-version {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.active-version .number {
|
||||
color: var(--green);
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.active-version::after {
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-top: 6px solid #aaa;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.versions .active a {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.versions .versions-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.versions .versions-item .version-copy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.versions .versions-item:hover .version-copy {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
|
@ -1,4 +1,3 @@
|
|||
import { exportFiles } from '../store'
|
||||
import { saveAs } from 'file-saver'
|
||||
|
||||
import index from './template/index.html?raw'
|
||||
|
@ -6,8 +5,13 @@ import main from './template/main.js?raw'
|
|||
import pkg from './template/package.json?raw'
|
||||
import config from './template/vite.config.js?raw'
|
||||
import readme from './template/README.md?raw'
|
||||
import type { ReplStore } from '@vue/repl'
|
||||
|
||||
export async function downloadProject(store: ReplStore) {
|
||||
if (!confirm('Download project files?')) {
|
||||
return
|
||||
}
|
||||
|
||||
export async function downloadProject() {
|
||||
const { default: JSZip } = await import('jszip')
|
||||
const zip = new JSZip()
|
||||
|
||||
|
@ -21,9 +25,13 @@ export async function downloadProject() {
|
|||
const src = zip.folder('src')!
|
||||
src.file('main.js', main)
|
||||
|
||||
const files = exportFiles()
|
||||
const files = store.getFiles()
|
||||
for (const file in files) {
|
||||
src.file(file, files[file])
|
||||
if (file !== 'import-map.json' && file !== 'tsconfig.json') {
|
||||
src.file(file, files[file])
|
||||
} else {
|
||||
zip.file(file, files[file])
|
||||
}
|
||||
}
|
||||
|
||||
const blob = await zip.generateAsync({ type: 'blob' })
|
|
@ -1,6 +1,6 @@
|
|||
# Vite Vue Starter
|
||||
|
||||
This is a project template using [Vite](https://vitejs.dev/). It requires [Node.js](https://nodejs.org) v12+.
|
||||
This is a project template using [Vite](https://vitejs.dev/). It requires [Node.js](https://nodejs.org) version 18+ or 20+.
|
||||
|
||||
To start:
|
||||
|
||||
|
@ -11,4 +11,8 @@ npm run dev
|
|||
# if using yarn:
|
||||
yarn
|
||||
yarn dev
|
||||
|
||||
# if using pnpm:
|
||||
pnpm install
|
||||
pnpm run dev
|
||||
```
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
|
@ -1,17 +1,17 @@
|
|||
{
|
||||
"name": "vite-vue-starter",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.0.9"
|
||||
"vue": "^3.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^1.1.5",
|
||||
"@vue/compiler-sfc": "^3.0.9",
|
||||
"vite": "^2.1.3"
|
||||
"@vitejs/plugin-vue": "^5.1.3",
|
||||
"vite": "^5.4.2"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,5 +3,5 @@ import vue from '@vitejs/plugin-vue'
|
|||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()]
|
||||
plugins: [vue()],
|
||||
})
|
|
@ -0,0 +1,14 @@
|
|||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1.3em"
|
||||
height="1.3em"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path fill="currentColor" d="M8 7h11v14H8z" opacity=".3" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<svg width="1.7em" height="1.7em" viewBox="0 0 24 24" fill="currentColor">
|
||||
<g>
|
||||
<rect x="4" y="18" width="16" height="2" rx="1" ry="1" />
|
||||
<rect
|
||||
x="3"
|
||||
y="17"
|
||||
width="4"
|
||||
height="2"
|
||||
rx="1"
|
||||
ry="1"
|
||||
transform="rotate(-90 5 18)"
|
||||
/>
|
||||
<rect
|
||||
x="17"
|
||||
y="17"
|
||||
width="4"
|
||||
height="2"
|
||||
rx="1"
|
||||
ry="1"
|
||||
transform="rotate(-90 19 18)"
|
||||
/>
|
||||
<path
|
||||
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"
|
||||
/>
|
||||
<path d="M12 13a1 1 0 0 1-1-1V4a1 1 0 0 1 2 0v8a1 1 0 0 1-1 1z" />
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
|
@ -0,0 +1,7 @@
|
|||
<template>
|
||||
<svg width="1.7em" height="1.7em" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
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"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
|
@ -0,0 +1,8 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
|
@ -0,0 +1,14 @@
|
|||
<template>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
width="1.7em"
|
||||
height="1.7em"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
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"
|
||||
/>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
</template>
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<svg width="1.4em" height="1.4em" viewBox="0 0 24 24">
|
||||
<g
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<circle cx="18" cy="5" r="3" />
|
||||
<circle cx="6" cy="12" r="3" />
|
||||
<circle cx="18" cy="19" r="3" />
|
||||
<path d="M8.59 13.51l6.83 3.98" />
|
||||
<path d="M15.41 6.51l-6.82 3.98" />
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
|
@ -0,0 +1,40 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
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"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
|
@ -0,0 +1,9 @@
|
|||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
// @ts-expect-error Custom window property
|
||||
window.VUE_DEVTOOLS_CONFIG = {
|
||||
defaultSelectedAppId: 'repl',
|
||||
}
|
||||
|
||||
createApp(App).mount('#app')
|
|
@ -0,0 +1,2 @@
|
|||
// serve vue to the iframe sandbox during dev.
|
||||
export * from 'vue/dist/vue.runtime.esm-browser.prod.js'
|
|
@ -0,0 +1,2 @@
|
|||
// serve vue/server-renderer to the iframe sandbox during dev.
|
||||
export * from 'vue/server-renderer'
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"github": {
|
||||
"silent": true
|
||||
},
|
||||
"headers": [
|
||||
{
|
||||
"source": "/assets/(.*)",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "max-age=31536000, immutable"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue