mirror of https://github.com/vuejs/core.git
Merge branch 'main' into handle-symbol-unscopables-access
This commit is contained in:
commit
03ea8ff9bd
|
@ -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
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
|
|||
|
||||
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`.
|
||||
|
@ -82,7 +81,7 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
|
|||
|
||||
## Development Setup
|
||||
|
||||
You will need [Node.js](https://nodejs.org) **version 18.12+**, and [PNPM](https://pnpm.io) **version 8+**.
|
||||
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.
|
||||
|
||||
|
@ -237,7 +236,7 @@ Tests that test against source code are grouped under `nr test-unit`, while test
|
|||
|
||||
### `nr test-dts`
|
||||
|
||||
Runs `nr build-dts` first, then verify the type tests in `packages/dts-test` are working correctly against the actual built type declarations.
|
||||
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
|
||||
|
||||
|
@ -336,7 +335,7 @@ Test coverage is continuously deployed at https://coverage.vuejs.org. PRs that i
|
|||
|
||||
### Testing Type Definition Correctness
|
||||
|
||||
Type tests are located in the `packages/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`.
|
||||
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
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ Depending on the type of the PR, different considerations need to be taken into
|
|||
- 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
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
{
|
||||
groupName: 'playground',
|
||||
matchFileNames: [
|
||||
'packages/sfc-playground/package.json',
|
||||
'packages/template-explorer/package.json',
|
||||
'packages-private/sfc-playground/package.json',
|
||||
'packages-private/template-explorer/package.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -28,7 +28,7 @@
|
|||
},
|
||||
{
|
||||
groupName: 'build',
|
||||
matchPackageNames: ['vite', 'terser'],
|
||||
matchPackageNames: ['vite', '@swc/core'],
|
||||
matchPackagePrefixes: ['rollup', 'esbuild', '@rollup', '@vitejs'],
|
||||
},
|
||||
{
|
||||
|
@ -54,5 +54,13 @@
|
|||
// 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',
|
||||
],
|
||||
}
|
||||
|
|
|
@ -31,4 +31,4 @@ jobs:
|
|||
- name: Run prettier
|
||||
run: pnpm run format
|
||||
|
||||
- uses: autofix-ci/action@2891949f3779a1cafafae1523058501de3d4e944
|
||||
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
|
||||
|
|
|
@ -28,6 +28,6 @@ jobs:
|
|||
|
||||
- run: pnpm install
|
||||
|
||||
- run: pnpm release --canary --tag minor
|
||||
- run: pnpm release --canary --publish --tag minor
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
|
|
@ -26,6 +26,6 @@ jobs:
|
|||
|
||||
- run: pnpm install
|
||||
|
||||
- run: pnpm release --canary
|
||||
- run: pnpm release --canary --publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
|
|
@ -3,141 +3,40 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- '**'
|
||||
tags:
|
||||
- '!**'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- minor
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
unit-test:
|
||||
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
|
||||
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
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'
|
||||
|
||||
- run: pnpm install
|
||||
- name: Install deps
|
||||
run: pnpm install
|
||||
|
||||
- name: Run unit tests
|
||||
run: pnpm run test-unit
|
||||
- name: Build
|
||||
run: pnpm build --withTypes
|
||||
|
||||
unit-test-windows:
|
||||
runs-on: windows-latest
|
||||
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
||||
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
|
||||
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
||||
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
|
||||
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
||||
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
|
||||
|
||||
# benchmarks:
|
||||
# runs-on: ubuntu-latest
|
||||
# if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
||||
# env:
|
||||
# PUPPETEER_SKIP_DOWNLOAD: 'true'
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
|
||||
# - name: Install pnpm
|
||||
# uses: pnpm/action-setup@v3.0.0
|
||||
|
||||
# - name: Install Node.js
|
||||
# uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version-file: '.node-version'
|
||||
# cache: 'pnpm'
|
||||
|
||||
# - run: pnpm install
|
||||
|
||||
# - name: Run benchmarks
|
||||
# uses: CodSpeedHQ/action@v2
|
||||
# with:
|
||||
# run: pnpm vitest bench --run
|
||||
# token: ${{ secrets.CODSPEED_TOKEN }}
|
||||
- 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
|
|
@ -9,7 +9,8 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'vuejs/core' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run')
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
- name: Check user permission
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const user = context.payload.sender.login
|
||||
|
@ -43,7 +44,8 @@ jobs:
|
|||
})
|
||||
throw new Error('not allowed')
|
||||
}
|
||||
- uses: actions/github-script@v7
|
||||
- name: Get PR info
|
||||
uses: actions/github-script@v7
|
||||
id: get-pr-data
|
||||
with:
|
||||
script: |
|
||||
|
@ -56,9 +58,11 @@ jobs:
|
|||
return {
|
||||
num: context.issue.number,
|
||||
branchName: pr.head.ref,
|
||||
repo: pr.head.repo.full_name
|
||||
repo: pr.head.repo.full_name,
|
||||
commit: pr.head.sha
|
||||
}
|
||||
- uses: actions/github-script@v7
|
||||
- name: Trigger run
|
||||
uses: actions/github-script@v7
|
||||
id: trigger
|
||||
env:
|
||||
COMMENT: ${{ github.event.comment.body }}
|
||||
|
@ -80,6 +84,7 @@ jobs:
|
|||
prNumber: '' + prData.num,
|
||||
branchName: prData.branchName,
|
||||
repo: prData.repo,
|
||||
suite: suite === '' ? '-' : suite
|
||||
suite: suite === '' ? '-' : suite,
|
||||
commit: prData.commit
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
name: Create Release
|
||||
|
||||
permissions: {}
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: write # to create release (yyx990803/release-tag)
|
||||
|
||||
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: |
|
||||
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,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.
|
|
@ -4,6 +4,7 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- main
|
||||
- minor
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
@ -17,6 +18,7 @@ env:
|
|||
|
||||
jobs:
|
||||
upload:
|
||||
if: github.repository == 'vuejs/core'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
@ -36,18 +38,14 @@ jobs:
|
|||
|
||||
- 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
|
||||
|
||||
- name: Save PR number
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
run: echo ${{ github.event.number }} > ./pr.txt
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
with:
|
||||
name: pr-number
|
||||
path: pr.txt
|
||||
|
|
|
@ -18,6 +18,7 @@ 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:
|
||||
|
@ -35,19 +36,6 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Download PR number
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
name: pr-number
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
path: /tmp/pr-number
|
||||
|
||||
- name: Read PR Number
|
||||
id: pr-number
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: /tmp/pr-number/pr.txt
|
||||
|
||||
- name: Download Size Data
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
|
@ -55,10 +43,22 @@ jobs:
|
|||
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: main
|
||||
branch: ${{ steps.pr-base.outputs.content }}
|
||||
workflow: size-data.yml
|
||||
event: push
|
||||
name: size-data
|
||||
|
@ -66,7 +66,7 @@ jobs:
|
|||
if_no_artifact_found: warn
|
||||
|
||||
- name: Prepare report
|
||||
run: pnpm tsx scripts/size-report.ts > size-report.md
|
||||
run: node scripts/size-report.js > size-report.md
|
||||
|
||||
- name: Read Size Report
|
||||
id: size-report
|
||||
|
|
|
@ -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
|
|
@ -1,4 +1,3 @@
|
|||
dist
|
||||
*.md
|
||||
*.html
|
||||
pnpm-lock.yaml
|
||||
CHANGELOG*.md
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"recommendations": ["vitest.explorer"]
|
||||
}
|
1162
CHANGELOG.md
1162
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
|
@ -10,6 +10,6 @@ Please note that we do not consider XSS via template expressions a valid attack
|
|||
|
||||
We would like to thank the following security researchers for responsibly disclosing security issues to us.
|
||||
|
||||
- Jeet Pal - [@jeetpal2007](https://github.com/jeetpal2007) | [Email](jeetpal2007@gmail.com) | [LinkedIn](https://in.linkedin.com/in/jeet-pal-22601a290 )
|
||||
- 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>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
import importX from 'eslint-plugin-import-x'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import vitest from 'eslint-plugin-vitest'
|
||||
import vitest from '@vitest/eslint-plugin'
|
||||
import { builtinModules } from 'node:module'
|
||||
|
||||
const DOMGlobals = ['window', 'document']
|
||||
|
@ -76,7 +76,11 @@ export default tseslint.config(
|
|||
|
||||
// tests, no restrictions (runs in Node / Vitest with jsdom)
|
||||
{
|
||||
files: ['**/__tests__/**', 'packages/dts-test/**'],
|
||||
files: [
|
||||
'**/__tests__/**',
|
||||
'packages-private/dts-test/**',
|
||||
'packages-private/dts-build-test/**',
|
||||
],
|
||||
plugins: { vitest },
|
||||
languageOptions: {
|
||||
globals: {
|
||||
|
@ -119,7 +123,10 @@ export default tseslint.config(
|
|||
|
||||
// Private package, browser only + no syntax restrictions
|
||||
{
|
||||
files: ['packages/template-explorer/**', 'packages/sfc-playground/**'],
|
||||
files: [
|
||||
'packages-private/template-explorer/**',
|
||||
'packages-private/sfc-playground/**',
|
||||
],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
|
|
83
package.json
83
package.json
|
@ -1,14 +1,14 @@
|
|||
{
|
||||
"private": true,
|
||||
"version": "3.4.31",
|
||||
"packageManager": "pnpm@9.5.0",
|
||||
"version": "3.5.11",
|
||||
"packageManager": "pnpm@9.12.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "node scripts/dev.js",
|
||||
"build": "node scripts/build.js",
|
||||
"build-dts": "tsc -p tsconfig.build-browser.json && tsc -p tsconfig.build-node.json && rollup -c rollup.dts.config.js",
|
||||
"clean": "rimraf packages/*/dist temp .eslintcache",
|
||||
"size": "run-s \"size-*\" && tsx scripts/usage-size.ts",
|
||||
"build-dts": "tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js",
|
||||
"clean": "rimraf --glob packages/*/dist temp .eslintcache",
|
||||
"size": "run-s \"size-*\" && node scripts/usage-size.js",
|
||||
"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",
|
||||
|
@ -17,11 +17,11 @@
|
|||
"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-unit": "vitest --project unit",
|
||||
"test-e2e": "node scripts/build.js vue -f global -d && vitest --project e2e",
|
||||
"test-dts": "run-s build-dts test-dts-only",
|
||||
"test-dts-only": "tsc -p packages/dts-built-test/tsconfig.json && tsc -p ./packages/dts-test/tsconfig.test.json",
|
||||
"test-coverage": "vitest -c vitest.unit.config.ts --coverage",
|
||||
"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 --project unit --coverage",
|
||||
"test-bench": "vitest bench",
|
||||
"release": "node scripts/release.js",
|
||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
|
||||
|
@ -29,16 +29,16 @@
|
|||
"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/sfc-playground --host",
|
||||
"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:3000/packages/template-explorer/local.html",
|
||||
"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/sfc-playground && npm run build",
|
||||
"build-sfc-playground-self": "cd packages-private/sfc-playground && npm run build",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"postinstall": "simple-git-hooks"
|
||||
},
|
||||
|
@ -61,54 +61,53 @@
|
|||
"devDependencies": {
|
||||
"@babel/parser": "catalog:",
|
||||
"@babel/types": "catalog:",
|
||||
"@codspeed/vitest-plugin": "^3.1.0",
|
||||
"@rollup/plugin-alias": "^5.1.0",
|
||||
"@rollup/plugin-commonjs": "^26.0.1",
|
||||
"@rollup/plugin-alias": "^5.1.1",
|
||||
"@rollup/plugin-commonjs": "^28.0.0",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||
"@rollup/plugin-replace": "5.0.4",
|
||||
"@swc/core": "^1.6.13",
|
||||
"@swc/core": "^1.7.28",
|
||||
"@types/hash-sum": "^1.0.2",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/node": "^20.16.10",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@vitest/coverage-istanbul": "^1.6.0",
|
||||
"@types/serve-handler": "^6.1.4",
|
||||
"@vitest/coverage-v8": "^2.1.1",
|
||||
"@vue/consolidate": "1.0.0",
|
||||
"conventional-changelog-cli": "^4.1.0",
|
||||
"conventional-changelog-cli": "^5.0.0",
|
||||
"enquirer": "^2.4.1",
|
||||
"esbuild": "^0.23.0",
|
||||
"esbuild": "^0.24.0",
|
||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||
"eslint": "^9.6.0",
|
||||
"eslint-plugin-import-x": "^0.5.3",
|
||||
"eslint-plugin-vitest": "^0.5.4",
|
||||
"estree-walker": "^2.0.2",
|
||||
"jsdom": "^24.1.0",
|
||||
"lint-staged": "^15.2.7",
|
||||
"eslint": "^9.12.0",
|
||||
"eslint-plugin-import-x": "^4.3.1",
|
||||
"@vitest/eslint-plugin": "^1.0.1",
|
||||
"estree-walker": "catalog:",
|
||||
"jsdom": "^25.0.0",
|
||||
"lint-staged": "^15.2.10",
|
||||
"lodash": "^4.17.21",
|
||||
"magic-string": "^0.30.10",
|
||||
"magic-string": "^0.30.11",
|
||||
"markdown-table": "^3.0.3",
|
||||
"marked": "^12.0.2",
|
||||
"npm-run-all2": "^6.2.2",
|
||||
"picocolors": "^1.0.1",
|
||||
"prettier": "^3.3.2",
|
||||
"marked": "13.0.3",
|
||||
"npm-run-all2": "^6.2.3",
|
||||
"picocolors": "^1.1.0",
|
||||
"prettier": "^3.3.3",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
"pug": "^3.0.3",
|
||||
"puppeteer": "~22.12.1",
|
||||
"rimraf": "^5.0.8",
|
||||
"rollup": "^4.18.0",
|
||||
"puppeteer": "~23.3.0",
|
||||
"rimraf": "^6.0.1",
|
||||
"rollup": "^4.24.0",
|
||||
"rollup-plugin-dts": "^6.1.1",
|
||||
"rollup-plugin-esbuild": "^6.1.1",
|
||||
"rollup-plugin-polyfill-node": "^0.13.0",
|
||||
"semver": "^7.6.2",
|
||||
"semver": "^7.6.3",
|
||||
"serve": "^14.2.3",
|
||||
"serve-handler": "^6.1.5",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"terser": "^5.31.1",
|
||||
"todomvc-app-css": "^2.4.3",
|
||||
"tslib": "^2.6.3",
|
||||
"tsx": "^4.16.2",
|
||||
"typescript": "~5.4.5",
|
||||
"typescript-eslint": "^7.15.0",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "~5.6.2",
|
||||
"typescript-eslint": "^8.8.0",
|
||||
"vite": "catalog:",
|
||||
"vitest": "^1.6.0"
|
||||
"vitest": "^2.1.1"
|
||||
},
|
||||
"pnpm": {
|
||||
"peerDependencyRules": {
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
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/dts-test/built.test-d.ts`](https://github.com/vuejs/core/blob/main/packages/dts-test/built.test-d.ts) to verify that the built types work correctly.
|
||||
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.
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@vue/dts-built-test",
|
||||
"name": "dts-built-test",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"types": "dist/index.d.ts",
|
|
@ -4,4 +4,4 @@ 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/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-types`.
|
||||
- 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,19 @@
|
|||
import { createApp } from 'vue'
|
||||
import { expectType } from './utils'
|
||||
|
||||
const app = createApp({})
|
||||
|
||||
app.directive<HTMLElement, string, 'prevent' | 'stop', 'arg1' | 'arg2'>(
|
||||
'custom',
|
||||
{
|
||||
mounted(el, binding) {
|
||||
expectType<HTMLElement>(el)
|
||||
expectType<string>(binding.value)
|
||||
expectType<{ prevent: boolean; stop: boolean }>(binding.modifiers)
|
||||
expectType<'arg1' | 'arg2'>(binding.arg!)
|
||||
|
||||
// @ts-expect-error not any
|
||||
expectType<number>(binding.value)
|
||||
},
|
||||
},
|
||||
)
|
|
@ -1,4 +1,4 @@
|
|||
import { CustomPropsNotErased } from '@vue/dts-built-test'
|
||||
import { CustomPropsNotErased } from 'dts-built-test/src/index'
|
||||
import { describe, expectType } from './utils'
|
||||
|
||||
declare module 'vue' {
|
|
@ -1,4 +1,4 @@
|
|||
import { defineComponent } from 'vue'
|
||||
import { type DefineComponent, type Directive, defineComponent } from 'vue'
|
||||
import { expectType } from './utils'
|
||||
|
||||
declare module 'vue' {
|
||||
|
@ -6,6 +6,14 @@ declare module 'vue' {
|
|||
test?(n: number): void
|
||||
}
|
||||
|
||||
interface GlobalDirectives {
|
||||
test: Directive
|
||||
}
|
||||
|
||||
interface GlobalComponents {
|
||||
RouterView: DefineComponent<{}>
|
||||
}
|
||||
|
||||
interface ComponentCustomProperties {
|
||||
state?: 'stopped' | 'running'
|
||||
}
|
||||
|
@ -46,6 +54,8 @@ export const Custom = defineComponent({
|
|||
},
|
||||
})
|
||||
|
||||
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} />)
|
|
@ -15,7 +15,7 @@ import {
|
|||
withKeys,
|
||||
withModifiers,
|
||||
} from 'vue'
|
||||
import { type IsUnion, describe, expectType } from './utils'
|
||||
import { type IsAny, type IsUnion, describe, expectType } from './utils'
|
||||
|
||||
describe('with object props', () => {
|
||||
interface ExpectedProps {
|
||||
|
@ -480,6 +480,26 @@ describe('type inference w/ options API', () => {
|
|||
})
|
||||
})
|
||||
|
||||
// #4051
|
||||
describe('type inference w/ empty prop object', () => {
|
||||
const MyComponent = defineComponent({
|
||||
props: {},
|
||||
setup(props) {
|
||||
return {}
|
||||
},
|
||||
render() {},
|
||||
})
|
||||
expectType<JSX.Element>(<MyComponent />)
|
||||
// AllowedComponentProps
|
||||
expectType<JSX.Element>(<MyComponent class={'foo'} />)
|
||||
// ComponentCustomProps
|
||||
expectType<JSX.Element>(<MyComponent custom={1} />)
|
||||
// VNodeProps
|
||||
expectType<JSX.Element>(<MyComponent key="1" />)
|
||||
// @ts-expect-error
|
||||
expectError(<MyComponent other="other" />)
|
||||
})
|
||||
|
||||
describe('with mixins', () => {
|
||||
const MixinA = defineComponent({
|
||||
emits: ['bar'],
|
||||
|
@ -906,12 +926,15 @@ describe('emits', () => {
|
|||
emits: {
|
||||
click: (n: number) => typeof n === 'number',
|
||||
input: (b: string) => b.length > 1,
|
||||
Focus: (f: boolean) => !!f,
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
expectType<((n: number) => boolean) | undefined>(props.onClick)
|
||||
expectType<((b: string) => boolean) | undefined>(props.onInput)
|
||||
expectType<((f: boolean) => boolean) | undefined>(props.onFocus)
|
||||
emit('click', 1)
|
||||
emit('input', 'foo')
|
||||
emit('Focus', true)
|
||||
// @ts-expect-error
|
||||
emit('nope')
|
||||
// @ts-expect-error
|
||||
|
@ -922,6 +945,10 @@ describe('emits', () => {
|
|||
emit('input')
|
||||
// @ts-expect-error
|
||||
emit('input', 1)
|
||||
// @ts-expect-error
|
||||
emit('focus')
|
||||
// @ts-expect-error
|
||||
emit('focus', true)
|
||||
},
|
||||
created() {
|
||||
this.$emit('click', 1)
|
||||
|
@ -936,6 +963,10 @@ describe('emits', () => {
|
|||
this.$emit('input')
|
||||
// @ts-expect-error
|
||||
this.$emit('input', 1)
|
||||
// @ts-expect-error
|
||||
this.$emit('focus')
|
||||
// @ts-expect-error
|
||||
this.$emit('focus', true)
|
||||
},
|
||||
mounted() {
|
||||
// #3599
|
||||
|
@ -954,6 +985,10 @@ describe('emits', () => {
|
|||
this.$emit('input')
|
||||
// @ts-expect-error
|
||||
this.$emit('input', 1)
|
||||
// @ts-expect-error
|
||||
this.$emit('focus')
|
||||
// @ts-expect-error
|
||||
this.$emit('focus', true)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
@ -1006,6 +1041,18 @@ describe('emits', () => {
|
|||
},
|
||||
})
|
||||
|
||||
// #11803 manual props annotation in setup()
|
||||
const Hello = defineComponent({
|
||||
name: 'HelloWorld',
|
||||
inheritAttrs: false,
|
||||
props: { foo: String },
|
||||
emits: {
|
||||
customClick: (args: string) => typeof args === 'string',
|
||||
},
|
||||
setup(props: { foo?: string }) {},
|
||||
})
|
||||
;<Hello onCustomClick={() => {}} />
|
||||
|
||||
// without emits
|
||||
defineComponent({
|
||||
setup(props, { emit }) {
|
||||
|
@ -1505,14 +1552,104 @@ describe('withKeys and withModifiers as pro', () => {
|
|||
;<input onKeydown={onKeydown} onClick={onClick} />
|
||||
})
|
||||
|
||||
// #3367 expose components types
|
||||
describe('expose component types', () => {
|
||||
const child = defineComponent({
|
||||
props: {
|
||||
a: String,
|
||||
},
|
||||
})
|
||||
|
||||
const parent = defineComponent({
|
||||
components: {
|
||||
child,
|
||||
child2: {
|
||||
template: `<div></div>`,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expectType<typeof child>(parent.components!.child)
|
||||
expectType<Component>(parent.components!.child2)
|
||||
|
||||
// global components
|
||||
expectType<Readonly<KeepAliveProps>>(
|
||||
new parent.components!.KeepAlive().$props,
|
||||
)
|
||||
expectType<Readonly<KeepAliveProps>>(new child.components!.KeepAlive().$props)
|
||||
|
||||
// runtime-dom components
|
||||
expectType<Readonly<TransitionProps>>(
|
||||
new parent.components!.Transition().$props,
|
||||
)
|
||||
expectType<Readonly<TransitionProps>>(
|
||||
new child.components!.Transition().$props,
|
||||
)
|
||||
})
|
||||
|
||||
describe('directive typing', () => {
|
||||
const customDirective: Directive = {
|
||||
created(_) {},
|
||||
}
|
||||
|
||||
const comp = defineComponent({
|
||||
props: {
|
||||
a: String,
|
||||
},
|
||||
directives: {
|
||||
customDirective,
|
||||
localDirective: {
|
||||
created(_, { arg }) {
|
||||
expectType<string | undefined>(arg)
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expectType<typeof customDirective>(comp.directives!.customDirective)
|
||||
expectType<Directive>(comp.directives!.localDirective)
|
||||
|
||||
// global directive
|
||||
expectType<typeof vShow>(comp.directives!.vShow)
|
||||
})
|
||||
|
||||
describe('expose typing', () => {
|
||||
const Comp = defineComponent({
|
||||
expose: ['a', 'b'],
|
||||
props: {
|
||||
some: String,
|
||||
},
|
||||
data() {
|
||||
return { a: 1, b: '2', c: 1 }
|
||||
},
|
||||
})
|
||||
|
||||
expectType<Array<'a' | 'b'>>(Comp.expose!)
|
||||
|
||||
const vm = new Comp()
|
||||
// internal should still be exposed
|
||||
vm.$props
|
||||
|
||||
expectType<number>(vm.a)
|
||||
expectType<string>(vm.b)
|
||||
|
||||
// @ts-expect-error shouldn't be exposed
|
||||
vm.c
|
||||
})
|
||||
|
||||
import type {
|
||||
AllowedComponentProps,
|
||||
ComponentCustomProps,
|
||||
ComponentInstance,
|
||||
ComponentOptionsMixin,
|
||||
DefineComponent,
|
||||
Directive,
|
||||
EmitsOptions,
|
||||
ExtractPropTypes,
|
||||
KeepAliveProps,
|
||||
TransitionProps,
|
||||
VNodeProps,
|
||||
vShow,
|
||||
} from 'vue'
|
||||
|
||||
// code generated by tsc / vue-tsc, make sure this continues to work
|
||||
|
@ -1533,3 +1670,401 @@ declare const MyButton: DefineComponent<
|
|||
{}
|
||||
>
|
||||
;<MyButton class="x" />
|
||||
|
||||
describe('__typeProps backdoor for union type for conditional props', () => {
|
||||
interface CommonProps {
|
||||
size?: 'xl' | 'l' | 'm' | 's' | 'xs'
|
||||
}
|
||||
|
||||
type ConditionalProps =
|
||||
| {
|
||||
color?: 'normal' | 'primary' | 'secondary'
|
||||
appearance?: 'normal' | 'outline' | 'text'
|
||||
}
|
||||
| {
|
||||
color: 'white'
|
||||
appearance: 'outline'
|
||||
}
|
||||
|
||||
type Props = CommonProps & ConditionalProps
|
||||
|
||||
const Comp = defineComponent({
|
||||
__typeProps: {} as Props,
|
||||
})
|
||||
// @ts-expect-error
|
||||
;<Comp color="white" />
|
||||
// @ts-expect-error
|
||||
;<Comp color="white" appearance="normal" />
|
||||
;<Comp color="white" appearance="outline" />
|
||||
|
||||
const c = new Comp()
|
||||
|
||||
// @ts-expect-error
|
||||
c.$props = { color: 'white' }
|
||||
// @ts-expect-error
|
||||
c.$props = { color: 'white', appearance: 'text' }
|
||||
c.$props = { color: 'white', appearance: 'outline' }
|
||||
})
|
||||
|
||||
describe('__typeEmits backdoor, 3.3+ object syntax', () => {
|
||||
type Emits = {
|
||||
change: [id: number]
|
||||
update: [value: string]
|
||||
}
|
||||
|
||||
const Comp = defineComponent({
|
||||
__typeEmits: {} as Emits,
|
||||
mounted() {
|
||||
this.$props.onChange?.(123)
|
||||
// @ts-expect-error
|
||||
this.$props.onChange?.('123')
|
||||
this.$props.onUpdate?.('foo')
|
||||
// @ts-expect-error
|
||||
this.$props.onUpdate?.(123)
|
||||
|
||||
// @ts-expect-error
|
||||
this.$emit('foo')
|
||||
|
||||
this.$emit('change', 123)
|
||||
// @ts-expect-error
|
||||
this.$emit('change', '123')
|
||||
|
||||
this.$emit('update', 'test')
|
||||
// @ts-expect-error
|
||||
this.$emit('update', 123)
|
||||
},
|
||||
})
|
||||
|
||||
;<Comp onChange={id => id.toFixed(2)} />
|
||||
;<Comp onUpdate={id => id.toUpperCase()} />
|
||||
// @ts-expect-error
|
||||
;<Comp onChange={id => id.slice(1)} />
|
||||
// @ts-expect-error
|
||||
;<Comp onUpdate={id => id.toFixed(2)} />
|
||||
|
||||
const c = new Comp()
|
||||
// @ts-expect-error
|
||||
c.$emit('foo')
|
||||
|
||||
c.$emit('change', 123)
|
||||
// @ts-expect-error
|
||||
c.$emit('change', '123')
|
||||
|
||||
c.$emit('update', 'test')
|
||||
// @ts-expect-error
|
||||
c.$emit('update', 123)
|
||||
})
|
||||
|
||||
describe('__typeEmits backdoor, call signature syntax', () => {
|
||||
type Emits = {
|
||||
(e: 'change', id: number): void
|
||||
(e: 'update', value: string): void
|
||||
}
|
||||
|
||||
const Comp = defineComponent({
|
||||
__typeEmits: {} as Emits,
|
||||
mounted() {
|
||||
this.$props.onChange?.(123)
|
||||
// @ts-expect-error
|
||||
this.$props.onChange?.('123')
|
||||
this.$props.onUpdate?.('foo')
|
||||
// @ts-expect-error
|
||||
this.$props.onUpdate?.(123)
|
||||
|
||||
// @ts-expect-error
|
||||
this.$emit('foo')
|
||||
|
||||
this.$emit('change', 123)
|
||||
// @ts-expect-error
|
||||
this.$emit('change', '123')
|
||||
|
||||
this.$emit('update', 'test')
|
||||
// @ts-expect-error
|
||||
this.$emit('update', 123)
|
||||
},
|
||||
})
|
||||
|
||||
;<Comp onChange={id => id.toFixed(2)} />
|
||||
;<Comp onUpdate={id => id.toUpperCase()} />
|
||||
// @ts-expect-error
|
||||
;<Comp onChange={id => id.slice(1)} />
|
||||
// @ts-expect-error
|
||||
;<Comp onUpdate={id => id.toFixed(2)} />
|
||||
|
||||
const c = new Comp()
|
||||
// @ts-expect-error
|
||||
c.$emit('foo')
|
||||
|
||||
c.$emit('change', 123)
|
||||
// @ts-expect-error
|
||||
c.$emit('change', '123')
|
||||
|
||||
c.$emit('update', 'test')
|
||||
// @ts-expect-error
|
||||
c.$emit('update', 123)
|
||||
})
|
||||
|
||||
describe('__typeRefs backdoor, object syntax', () => {
|
||||
type Refs = {
|
||||
foo: number
|
||||
}
|
||||
|
||||
const Parent = defineComponent({
|
||||
__typeRefs: {} as { child: ComponentInstance<typeof Child> },
|
||||
})
|
||||
const Child = defineComponent({
|
||||
__typeRefs: {} as Refs,
|
||||
})
|
||||
const c = new Parent()
|
||||
const refs = c.$refs
|
||||
|
||||
expectType<ComponentInstance<typeof Child>>(refs.child)
|
||||
expectType<number>(refs.child.$refs.foo)
|
||||
})
|
||||
|
||||
describe('__typeEl backdoor', () => {
|
||||
const Comp = defineComponent({
|
||||
__typeEl: {} as HTMLAnchorElement,
|
||||
})
|
||||
const c = new Comp()
|
||||
|
||||
expectType<HTMLAnchorElement>(c.$el)
|
||||
})
|
||||
|
||||
defineComponent({
|
||||
props: {
|
||||
foo: [String, null],
|
||||
},
|
||||
setup(props) {
|
||||
expectType<IsAny<typeof props.foo>>(false)
|
||||
expectType<string | null | undefined>(props.foo)
|
||||
},
|
||||
})
|
||||
|
||||
import type * as vue from 'vue'
|
||||
|
||||
interface ErrorMessageSlotProps {
|
||||
message: string | undefined
|
||||
}
|
||||
/**
|
||||
* #10842
|
||||
* component types generated by vue-tsc
|
||||
* relying on legacy CreateComponentPublicInstance signature
|
||||
*/
|
||||
declare const ErrorMessage: {
|
||||
new (...args: any[]): vue.CreateComponentPublicInstance<
|
||||
Readonly<
|
||||
vue.ExtractPropTypes<{
|
||||
as: {
|
||||
type: StringConstructor
|
||||
default: any
|
||||
}
|
||||
name: {
|
||||
type: StringConstructor
|
||||
required: true
|
||||
}
|
||||
}>
|
||||
>,
|
||||
() =>
|
||||
| VNode<
|
||||
vue.RendererNode,
|
||||
vue.RendererElement,
|
||||
{
|
||||
[key: string]: any
|
||||
}
|
||||
>
|
||||
| vue.Slot<any>
|
||||
| VNode<
|
||||
vue.RendererNode,
|
||||
vue.RendererElement,
|
||||
{
|
||||
[key: string]: any
|
||||
}
|
||||
>[]
|
||||
| {
|
||||
default: () => VNode<
|
||||
vue.RendererNode,
|
||||
vue.RendererElement,
|
||||
{
|
||||
[key: string]: any
|
||||
}
|
||||
>[]
|
||||
},
|
||||
unknown,
|
||||
{},
|
||||
{},
|
||||
vue.ComponentOptionsMixin,
|
||||
vue.ComponentOptionsMixin,
|
||||
{},
|
||||
vue.VNodeProps &
|
||||
vue.AllowedComponentProps &
|
||||
vue.ComponentCustomProps &
|
||||
Readonly<
|
||||
vue.ExtractPropTypes<{
|
||||
as: {
|
||||
type: StringConstructor
|
||||
default: any
|
||||
}
|
||||
name: {
|
||||
type: StringConstructor
|
||||
required: true
|
||||
}
|
||||
}>
|
||||
>,
|
||||
{
|
||||
as: string
|
||||
},
|
||||
true,
|
||||
{},
|
||||
{},
|
||||
{
|
||||
P: {}
|
||||
B: {}
|
||||
D: {}
|
||||
C: {}
|
||||
M: {}
|
||||
Defaults: {}
|
||||
},
|
||||
Readonly<
|
||||
vue.ExtractPropTypes<{
|
||||
as: {
|
||||
type: StringConstructor
|
||||
default: any
|
||||
}
|
||||
name: {
|
||||
type: StringConstructor
|
||||
required: true
|
||||
}
|
||||
}>
|
||||
>,
|
||||
() =>
|
||||
| VNode<
|
||||
vue.RendererNode,
|
||||
vue.RendererElement,
|
||||
{
|
||||
[key: string]: any
|
||||
}
|
||||
>
|
||||
| vue.Slot<any>
|
||||
| VNode<
|
||||
vue.RendererNode,
|
||||
vue.RendererElement,
|
||||
{
|
||||
[key: string]: any
|
||||
}
|
||||
>[]
|
||||
| {
|
||||
default: () => VNode<
|
||||
vue.RendererNode,
|
||||
vue.RendererElement,
|
||||
{
|
||||
[key: string]: any
|
||||
}
|
||||
>[]
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
as: string
|
||||
}
|
||||
>
|
||||
__isFragment?: never
|
||||
__isTeleport?: never
|
||||
__isSuspense?: never
|
||||
} & vue.ComponentOptionsBase<
|
||||
Readonly<
|
||||
vue.ExtractPropTypes<{
|
||||
as: {
|
||||
type: StringConstructor
|
||||
default: any
|
||||
}
|
||||
name: {
|
||||
type: StringConstructor
|
||||
required: true
|
||||
}
|
||||
}>
|
||||
>,
|
||||
() =>
|
||||
| VNode<
|
||||
vue.RendererNode,
|
||||
vue.RendererElement,
|
||||
{
|
||||
[key: string]: any
|
||||
}
|
||||
>
|
||||
| vue.Slot<any>
|
||||
| VNode<
|
||||
vue.RendererNode,
|
||||
vue.RendererElement,
|
||||
{
|
||||
[key: string]: any
|
||||
}
|
||||
>[]
|
||||
| {
|
||||
default: () => VNode<
|
||||
vue.RendererNode,
|
||||
vue.RendererElement,
|
||||
{
|
||||
[key: string]: any
|
||||
}
|
||||
>[]
|
||||
},
|
||||
unknown,
|
||||
{},
|
||||
{},
|
||||
vue.ComponentOptionsMixin,
|
||||
vue.ComponentOptionsMixin,
|
||||
{},
|
||||
string,
|
||||
{
|
||||
as: string
|
||||
},
|
||||
{},
|
||||
string,
|
||||
{}
|
||||
> &
|
||||
vue.VNodeProps &
|
||||
vue.AllowedComponentProps &
|
||||
vue.ComponentCustomProps &
|
||||
(new () => {
|
||||
$slots: {
|
||||
default: (arg: ErrorMessageSlotProps) => VNode[]
|
||||
}
|
||||
})
|
||||
;<ErrorMessage name="password" class="error" />
|
||||
|
||||
// #10843
|
||||
createApp({}).component(
|
||||
'SomeComponent',
|
||||
defineComponent({
|
||||
props: {
|
||||
title: String,
|
||||
},
|
||||
setup(props) {
|
||||
expectType<string | undefined>(props.title)
|
||||
return {}
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
const Comp = defineComponent({
|
||||
props: {
|
||||
actionText: {
|
||||
type: {} as PropType<string>,
|
||||
default: 'Become a sponsor',
|
||||
},
|
||||
},
|
||||
__typeProps: {} as {
|
||||
actionText?: string
|
||||
},
|
||||
})
|
||||
|
||||
const instance = new Comp()
|
||||
function expectString(s: string) {}
|
||||
// instance prop with default should be non-null
|
||||
expectString(instance.actionText)
|
||||
|
||||
// public prop on $props should be optional
|
||||
// @ts-expect-error
|
||||
expectString(instance.$props.actionText)
|
|
@ -68,7 +68,7 @@ describe('inject', () => {
|
|||
})
|
||||
|
||||
describe('defineCustomElement using defineComponent return type', () => {
|
||||
test('with emits', () => {
|
||||
test('with object emits', () => {
|
||||
const Comp1Vue = defineComponent({
|
||||
props: {
|
||||
a: String,
|
||||
|
@ -80,6 +80,56 @@ describe('defineCustomElement using defineComponent return type', () => {
|
|||
const Comp = defineCustomElement(Comp1Vue)
|
||||
expectType<VueElementConstructor>(Comp)
|
||||
|
||||
expectType<string | undefined>(new Comp().a)
|
||||
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'>())
|
||||
})
|
|
@ -2,6 +2,7 @@ import {
|
|||
type InjectionKey,
|
||||
type Ref,
|
||||
createApp,
|
||||
defineComponent,
|
||||
inject,
|
||||
provide,
|
||||
ref,
|
||||
|
@ -52,3 +53,9 @@ provide<Cube>(123, { size: 'foo' })
|
|||
const app = createApp({})
|
||||
// @ts-expect-error
|
||||
app.provide(injectionKeyRef, ref({}))
|
||||
|
||||
defineComponent({
|
||||
provide: {
|
||||
[injectionKeyRef]: { size: 'foo' },
|
||||
},
|
||||
})
|
|
@ -4,6 +4,6 @@
|
|||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"vue": "workspace:*",
|
||||
"@vue/dts-built-test": "workspace:*"
|
||||
"dts-built-test": "workspace:*"
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import {
|
|||
type Ref,
|
||||
type ShallowRef,
|
||||
type ToRefs,
|
||||
type WritableComputedRef,
|
||||
computed,
|
||||
isRef,
|
||||
proxyRefs,
|
||||
|
@ -17,6 +18,7 @@ import {
|
|||
toRefs,
|
||||
toValue,
|
||||
unref,
|
||||
useTemplateRef,
|
||||
} from 'vue'
|
||||
import { type IsAny, type IsUnion, describe, expectType } from './utils'
|
||||
|
||||
|
@ -172,6 +174,67 @@ describe('ref with generic', <T extends { name: string }>() => {
|
|||
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)
|
||||
})
|
||||
|
||||
describe('correctly unwraps nested refs', () => {
|
||||
const obj = {
|
||||
n: 24,
|
||||
ref: ref(24),
|
||||
nestedRef: ref({ n: ref(0) }),
|
||||
}
|
||||
|
||||
const a = ref(obj)
|
||||
expectType<number>(a.value.n)
|
||||
expectType<number>(a.value.ref)
|
||||
expectType<number>(a.value.nestedRef.n)
|
||||
|
||||
const b = reactive({ a })
|
||||
expectType<number>(b.a.n)
|
||||
expectType<number>(b.a.ref)
|
||||
expectType<number>(b.a.nestedRef.n)
|
||||
})
|
||||
|
||||
// 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')
|
||||
|
@ -452,3 +515,27 @@ describe('toRef <-> toValue', () => {
|
|||
),
|
||||
)
|
||||
})
|
||||
|
||||
// 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)
|
|
@ -5,6 +5,7 @@ import {
|
|||
defineComponent,
|
||||
defineEmits,
|
||||
defineModel,
|
||||
defineOptions,
|
||||
defineProps,
|
||||
defineSlots,
|
||||
toRefs,
|
||||
|
@ -42,7 +43,8 @@ describe('defineProps w/ generics', () => {
|
|||
test()
|
||||
})
|
||||
|
||||
describe('defineProps w/ type declaration + withDefaults', () => {
|
||||
describe('defineProps w/ type declaration + withDefaults', <T extends
|
||||
string>() => {
|
||||
const res = withDefaults(
|
||||
defineProps<{
|
||||
number?: number
|
||||
|
@ -55,6 +57,7 @@ describe('defineProps w/ type declaration + withDefaults', () => {
|
|||
z?: string
|
||||
bool?: boolean
|
||||
boolAndUndefined: boolean | undefined
|
||||
foo?: T
|
||||
}>(),
|
||||
{
|
||||
number: 123,
|
||||
|
@ -64,6 +67,7 @@ describe('defineProps w/ type declaration + withDefaults', () => {
|
|||
genStr: () => '',
|
||||
y: undefined,
|
||||
z: 'string',
|
||||
foo: '' as any,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -80,6 +84,7 @@ describe('defineProps w/ type declaration + withDefaults', () => {
|
|||
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)
|
||||
|
@ -137,6 +142,31 @@ describe('defineProps w/ object union + withDefaults', () => {
|
|||
>(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
|
||||
|
@ -197,6 +227,19 @@ describe('withDefaults w/ boolean type', () => {
|
|||
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({
|
||||
|
@ -384,6 +427,51 @@ describe('defineModel', () => {
|
|||
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', () => {
|
||||
|
@ -501,3 +589,21 @@ describe('toRefs w/ type declaration', () => {
|
|||
}>()
|
||||
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'],
|
||||
})
|
||||
})
|
|
@ -121,3 +121,5 @@ expectType<JSX.Element>(
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>,
|
||||
)
|
||||
// details
|
||||
expectType<JSX.Element>(<details name="details" />)
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
type ComputedRef,
|
||||
type MaybeRef,
|
||||
type Ref,
|
||||
computed,
|
||||
defineComponent,
|
||||
|
@ -203,3 +204,10 @@ defineComponent({
|
|||
expectType<{ foo: string }>(value)
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
const css: MaybeRef<string> = ''
|
||||
watch(ref(css), value => {
|
||||
expectType<string>(value)
|
||||
})
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/// <reference types="vite/client" />
|
||||
|
||||
// Global compile-time constants
|
||||
declare var __COMMIT__: string
|
||||
|
||||
declare module 'file-saver' {
|
||||
export function saveAs(blob: any, name: any): void
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
@ -7,13 +7,16 @@
|
|||
<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)
|
||||
) {
|
||||
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>
|
|
@ -9,11 +9,11 @@
|
|||
"serve": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"@vitejs/plugin-vue": "catalog:",
|
||||
"vite": "catalog:"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue/repl": "^4.3.1",
|
||||
"@vue/repl": "^4.4.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"jszip": "^3.10.1",
|
||||
"vue": "workspace:*"
|
Before Width: | Height: | Size: 261 B After Width: | Height: | Size: 261 B |
|
@ -14,6 +14,12 @@ setVH()
|
|||
|
||||
const useSSRMode = ref(false)
|
||||
|
||||
const AUTO_SAVE_STORAGE_KEY = 'vue-sfc-playground-auto-save'
|
||||
const initAutoSave: boolean = JSON.parse(
|
||||
localStorage.getItem(AUTO_SAVE_STORAGE_KEY) ?? 'true',
|
||||
)
|
||||
const autoSave = ref(initAutoSave)
|
||||
|
||||
const { productionMode, vueVersion, importMap } = useVueImportMap({
|
||||
runtimeDev: import.meta.env.PROD
|
||||
? `${location.origin}/vue.runtime.esm-browser.js`
|
||||
|
@ -54,7 +60,8 @@ const sfcOptions = computed(
|
|||
template: {
|
||||
isProd: productionMode.value,
|
||||
compilerOptions: {
|
||||
isCustomElement: (tag: string) => tag === 'mjx-container',
|
||||
isCustomElement: (tag: string) =>
|
||||
tag === 'mjx-container' || tag.startsWith('custom-'),
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
@ -88,6 +95,11 @@ function toggleSSR() {
|
|||
useSSRMode.value = !useSSRMode.value
|
||||
}
|
||||
|
||||
function toggleAutoSave() {
|
||||
autoSave.value = !autoSave.value
|
||||
localStorage.setItem(AUTO_SAVE_STORAGE_KEY, String(autoSave.value))
|
||||
}
|
||||
|
||||
function reloadPage() {
|
||||
replRef.value?.reload()
|
||||
}
|
||||
|
@ -110,9 +122,11 @@ onMounted(() => {
|
|||
:store="store"
|
||||
:prod="productionMode"
|
||||
:ssr="useSSRMode"
|
||||
:autoSave="autoSave"
|
||||
@toggle-theme="toggleTheme"
|
||||
@toggle-prod="toggleProdMode"
|
||||
@toggle-ssr="toggleSSR"
|
||||
@toggle-autosave="toggleAutoSave"
|
||||
@reload-page="reloadPage"
|
||||
/>
|
||||
<Repl
|
||||
|
@ -122,6 +136,8 @@ onMounted(() => {
|
|||
@keydown.ctrl.s.prevent
|
||||
@keydown.meta.s.prevent
|
||||
:ssr="useSSRMode"
|
||||
:model-value="autoSave"
|
||||
:editorOptions="{ autoSaveText: false }"
|
||||
:store="store"
|
||||
:showCompileOutput="true"
|
||||
:autoResize="true"
|
||||
|
@ -129,7 +145,13 @@ onMounted(() => {
|
|||
:preview-options="{
|
||||
customCode: {
|
||||
importCode: `import { initCustomFormatter } from 'vue'`,
|
||||
useCode: `initCustomFormatter()`,
|
||||
useCode: `if (window.devtoolsFormatters) {
|
||||
const index = window.devtoolsFormatters.findIndex((v) => v.__vue_custom_formatter)
|
||||
window.devtoolsFormatters.splice(index, 1)
|
||||
initCustomFormatter()
|
||||
} else {
|
||||
initCustomFormatter()
|
||||
}`,
|
||||
},
|
||||
}"
|
||||
/>
|
|
@ -14,11 +14,13 @@ const props = defineProps<{
|
|||
store: ReplStore
|
||||
prod: boolean
|
||||
ssr: boolean
|
||||
autoSave: boolean
|
||||
}>()
|
||||
const emit = defineEmits([
|
||||
'toggle-theme',
|
||||
'toggle-ssr',
|
||||
'toggle-prod',
|
||||
'toggle-autosave',
|
||||
'reload-page',
|
||||
])
|
||||
|
||||
|
@ -80,7 +82,7 @@ function toggleDark() {
|
|||
pkg="vue"
|
||||
label="Vue Version"
|
||||
>
|
||||
<li>
|
||||
<li :class="{ active: vueVersion === `@${currentCommit}` }">
|
||||
<a @click="resetVueVersion">This Commit ({{ currentCommit }})</a>
|
||||
</li>
|
||||
<li>
|
||||
|
@ -107,6 +109,14 @@ function toggleDark() {
|
|||
>
|
||||
<span>{{ ssr ? 'SSR ON' : 'SSR OFF' }}</span>
|
||||
</button>
|
||||
<button
|
||||
title="Toggle editor auto save mode"
|
||||
class="toggle-autosave"
|
||||
:class="{ enabled: autoSave }"
|
||||
@click="$emit('toggle-autosave')"
|
||||
>
|
||||
<span>{{ autoSave ? 'AutoSave ON' : 'AutoSave OFF' }}</span>
|
||||
</button>
|
||||
<button title="Toggle dark mode" class="toggle-dark" @click="toggleDark">
|
||||
<Sun class="light" />
|
||||
<Moon class="dark" />
|
||||
|
@ -125,7 +135,7 @@ function toggleDark() {
|
|||
<Download />
|
||||
</button>
|
||||
<a
|
||||
href="https://github.com/vuejs/core/tree/main/packages/sfc-playground"
|
||||
href="https://github.com/vuejs/core/tree/main/packages-private/sfc-playground"
|
||||
target="_blank"
|
||||
title="View on GitHub"
|
||||
class="github"
|
||||
|
@ -199,7 +209,8 @@ h1 img {
|
|||
}
|
||||
|
||||
.toggle-prod span,
|
||||
.toggle-ssr span {
|
||||
.toggle-ssr span,
|
||||
.toggle-autosave span {
|
||||
font-size: 12px;
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
|
@ -214,11 +225,13 @@ h1 img {
|
|||
background: var(--purple);
|
||||
}
|
||||
|
||||
.toggle-ssr span {
|
||||
.toggle-ssr span,
|
||||
.toggle-autosave span {
|
||||
background-color: var(--btn-bg);
|
||||
}
|
||||
|
||||
.toggle-ssr.enabled span {
|
||||
.toggle-ssr.enabled span,
|
||||
.toggle-autosave.enabled span {
|
||||
color: #fff;
|
||||
background-color: var(--green);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import Copy from './icons/Copy.vue'
|
||||
|
||||
const expanded = ref(false)
|
||||
const versions = ref<string[]>()
|
||||
|
@ -53,6 +54,12 @@ function setVersion(v: string) {
|
|||
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
|
||||
|
@ -74,8 +81,21 @@ onMounted(() => {
|
|||
|
||||
<ul class="versions" :class="{ expanded }">
|
||||
<li v-if="!versions"><a>loading versions...</a></li>
|
||||
<li v-for="ver of versions" :class="{ active: ver === version }">
|
||||
<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 />
|
||||
|
@ -115,4 +135,17 @@ onMounted(() => {
|
|||
.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,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
|
@ -11,7 +11,7 @@
|
|||
"vue": "^3.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"vite": "^5.3.3"
|
||||
"@vitejs/plugin-vue": "^5.1.4",
|
||||
"vite": "^5.4.8"
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -34,7 +34,7 @@ function copyVuePlugin(): Plugin {
|
|||
name: 'copy-vue',
|
||||
generateBundle() {
|
||||
const copyFile = (file: string) => {
|
||||
const filePath = path.resolve(__dirname, file)
|
||||
const filePath = path.resolve(__dirname, '../../packages', file)
|
||||
const basename = path.basename(file)
|
||||
if (!fs.existsSync(filePath)) {
|
||||
throw new Error(
|
||||
|
@ -49,11 +49,11 @@ function copyVuePlugin(): Plugin {
|
|||
})
|
||||
}
|
||||
|
||||
copyFile(`../vue/dist/vue.esm-browser.js`)
|
||||
copyFile(`../vue/dist/vue.esm-browser.prod.js`)
|
||||
copyFile(`../vue/dist/vue.runtime.esm-browser.js`)
|
||||
copyFile(`../vue/dist/vue.runtime.esm-browser.prod.js`)
|
||||
copyFile(`../server-renderer/dist/server-renderer.esm-browser.js`)
|
||||
copyFile(`vue/dist/vue.esm-browser.js`)
|
||||
copyFile(`vue/dist/vue.esm-browser.prod.js`)
|
||||
copyFile(`vue/dist/vue.runtime.esm-browser.js`)
|
||||
copyFile(`vue/dist/vue.runtime.esm-browser.prod.js`)
|
||||
copyFile(`server-renderer/dist/server-renderer.esm-browser.js`)
|
||||
},
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<title>Vue Template Explorer</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
data-name="vs/editor/editor.main"
|
||||
href="https://unpkg.com/monaco-editor@0.20.0/min/vs/editor/editor.main.css"
|
||||
/>
|
||||
<link rel="stylesheet" href="./style.css" />
|
||||
|
||||
<div id="header"></div>
|
||||
<div id="source" class="editor"></div>
|
||||
<div id="output" class="editor"></div>
|
||||
|
||||
<script src="https://unpkg.com/monaco-editor@0.20.0/min/vs/loader.js"></script>
|
||||
<script>
|
||||
require.config({
|
||||
paths: {
|
||||
vs: 'https://unpkg.com/monaco-editor@0.20.0/min/vs',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<script src="./dist/template-explorer.global.js"></script>
|
||||
<script>
|
||||
require(['vs/editor/editor.main'], init /* injected by build */)
|
||||
</script>
|
|
@ -0,0 +1,24 @@
|
|||
<title>Vue Template Explorer</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
data-name="vs/editor/editor.main"
|
||||
href="./node_modules/monaco-editor/min/vs/editor/editor.main.css"
|
||||
/>
|
||||
<link rel="stylesheet" href="./style.css" />
|
||||
|
||||
<div id="header"></div>
|
||||
<div id="source" class="editor"></div>
|
||||
<div id="output" class="editor"></div>
|
||||
|
||||
<script src="./node_modules/monaco-editor/min/vs/loader.js"></script>
|
||||
<script>
|
||||
require.config({
|
||||
paths: {
|
||||
vs: './node_modules/monaco-editor/min/vs',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<script src="./dist/template-explorer.global.js"></script>
|
||||
<script>
|
||||
require(['vs/editor/editor.main'], init /* injected by build */)
|
||||
</script>
|
|
@ -11,7 +11,7 @@
|
|||
"enableNonBrowserBranches": true
|
||||
},
|
||||
"dependencies": {
|
||||
"monaco-editor": "^0.50.0",
|
||||
"source-map-js": "^1.2.0"
|
||||
"monaco-editor": "^0.52.0",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedDeclarations": false
|
||||
},
|
||||
"include": ["."]
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const count = ref(0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button @click="count++">{{ count }}</button>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
button {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1 @@
|
|||
This package is used for debugging issues that are related to `@vitejs/plugin-vue`, or can only be reproduced in a Vite-based setup. It aims to be as close to production as possible so Vue packages are resolved to the dist files instead of source.
|
|
@ -0,0 +1,2 @@
|
|||
<script type="module" src="./main.ts"></script>
|
||||
<div id="app"></div>
|
|
@ -0,0 +1,6 @@
|
|||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.mount('#app')
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "vite-debug",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "catalog:",
|
||||
"vite": "catalog:",
|
||||
"vue": "workspace:*"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler"
|
||||
},
|
||||
"include": ["./*"]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
})
|
|
@ -19,12 +19,12 @@ export function render(_ctx, _cache) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen > CacheExpression w/ isVNode: true 1`] = `
|
||||
exports[`compiler: codegen > CacheExpression w/ isVOnce: true 1`] = `
|
||||
"
|
||||
export function render(_ctx, _cache) {
|
||||
return _cache[1] || (
|
||||
_setBlockTracking(-1),
|
||||
_cache[1] = foo,
|
||||
(_cache[1] = foo).cacheIndex = 1,
|
||||
_setBlockTracking(1),
|
||||
_cache[1]
|
||||
)
|
||||
|
@ -54,7 +54,7 @@ return function render(_ctx, _cache) {
|
|||
[foo + bar]: bar
|
||||
}, [
|
||||
_createElementVNode("p", { "some-key": "foo" })
|
||||
], 16)
|
||||
], 16 /* FULL_PROPS */)
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
@ -98,7 +98,7 @@ exports[`compiler: codegen > forNode 1`] = `
|
|||
"
|
||||
return function render(_ctx, _cache) {
|
||||
with (_ctx) {
|
||||
return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(), 1))
|
||||
return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(), 1 /* TEXT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`compiler: parse > Edge Cases > invalid html 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -86,7 +86,7 @@ exports[`compiler: parse > Edge Cases > invalid html 1`] = `
|
|||
|
||||
exports[`compiler: parse > Edge Cases > self closing multiple tag 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -280,7 +280,7 @@ exports[`compiler: parse > Edge Cases > self closing multiple tag 1`] = `
|
|||
|
||||
exports[`compiler: parse > Edge Cases > valid html 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -498,7 +498,7 @@ exports[`compiler: parse > Edge Cases > valid html 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > CDATA_IN_HTML_CONTENT > <template><![CDATA[cdata]]></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -550,7 +550,7 @@ exports[`compiler: parse > Errors > CDATA_IN_HTML_CONTENT > <template><![CDATA[c
|
|||
|
||||
exports[`compiler: parse > Errors > CDATA_IN_HTML_CONTENT > <template><svg><![CDATA[cdata]]></svg></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -643,7 +643,7 @@ exports[`compiler: parse > Errors > CDATA_IN_HTML_CONTENT > <template><svg><![CD
|
|||
|
||||
exports[`compiler: parse > Errors > DUPLICATE_ATTRIBUTE > <template><div id="" id=""></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -813,7 +813,7 @@ exports[`compiler: parse > Errors > DUPLICATE_ATTRIBUTE > <template><div id="" i
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template>< 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -883,7 +883,7 @@ exports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template>< 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template></ 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -953,7 +953,7 @@ exports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template></ 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[ 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -1028,7 +1028,7 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[ 1`]
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[cdata 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -1121,7 +1121,7 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[cdata
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!-- 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1173,7 +1173,7 @@ exports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!-- 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!--comment 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -1243,7 +1243,7 @@ exports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!--comment 1`] =
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <div></div 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1295,7 +1295,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <div></div 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1347,7 +1347,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1399,7 +1399,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1451,7 +1451,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id = 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1503,7 +1503,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id = 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1555,7 +1555,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1607,7 +1607,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc" 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1659,7 +1659,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc" 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc"/ 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -1729,7 +1729,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc"/ 1`] =
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1781,7 +1781,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc' 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -1833,7 +1833,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc' 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc'/ 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -1903,7 +1903,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc'/ 1`] =
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc / 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -1973,7 +1973,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc / 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -2025,7 +2025,7 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > MISSING_ATTRIBUTE_VALUE > <template><div id= /></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -2148,7 +2148,7 @@ exports[`compiler: parse > Errors > MISSING_ATTRIBUTE_VALUE > <template><div id=
|
|||
|
||||
exports[`compiler: parse > Errors > MISSING_ATTRIBUTE_VALUE > <template><div id= ></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -2271,7 +2271,7 @@ exports[`compiler: parse > Errors > MISSING_ATTRIBUTE_VALUE > <template><div id=
|
|||
|
||||
exports[`compiler: parse > Errors > MISSING_ATTRIBUTE_VALUE > <template><div id=></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -2394,7 +2394,7 @@ exports[`compiler: parse > Errors > MISSING_ATTRIBUTE_VALUE > <template><div id=
|
|||
|
||||
exports[`compiler: parse > Errors > MISSING_END_TAG_NAME > <template></></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -2446,7 +2446,7 @@ exports[`compiler: parse > Errors > MISSING_END_TAG_NAME > <template></></templa
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME > <template><div a"bc=''></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -2569,7 +2569,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME > <te
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME > <template><div a'bc=''></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -2692,7 +2692,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME > <te
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME > <template><div a<bc=''></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -2815,7 +2815,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME > <te
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar"></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -2938,7 +2938,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_V
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar'></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -3061,7 +3061,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_V
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar<div></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -3184,7 +3184,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_V
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar=baz></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -3307,7 +3307,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_V
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar\`></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -3430,7 +3430,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_V
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME > <template><div =></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -3537,7 +3537,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME > <template><div =foo=bar></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -3660,7 +3660,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME > <template><?xml?></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -3712,7 +3712,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME
|
|||
|
||||
exports[`compiler: parse > Errors > UNEXPECTED_SOLIDUS_IN_TAG > <template><div a/b></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -3850,7 +3850,7 @@ exports[`compiler: parse > Errors > UNEXPECTED_SOLIDUS_IN_TAG > <template><div a
|
|||
|
||||
exports[`compiler: parse > Errors > X_INVALID_END_TAG > <svg><![CDATA[</div>]]></svg> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -3920,7 +3920,7 @@ exports[`compiler: parse > Errors > X_INVALID_END_TAG > <svg><![CDATA[</div>]]><
|
|||
|
||||
exports[`compiler: parse > Errors > X_INVALID_END_TAG > <svg><!--</div>--></svg> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -3990,7 +3990,7 @@ exports[`compiler: parse > Errors > X_INVALID_END_TAG > <svg><!--</div>--></svg>
|
|||
|
||||
exports[`compiler: parse > Errors > X_INVALID_END_TAG > <template></div></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -4042,7 +4042,7 @@ exports[`compiler: parse > Errors > X_INVALID_END_TAG > <template></div></div></
|
|||
|
||||
exports[`compiler: parse > Errors > X_INVALID_END_TAG > <template></div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -4094,7 +4094,7 @@ exports[`compiler: parse > Errors > X_INVALID_END_TAG > <template></div></templa
|
|||
|
||||
exports[`compiler: parse > Errors > X_INVALID_END_TAG > <template>{{'</div>'}}</template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -4182,7 +4182,7 @@ exports[`compiler: parse > Errors > X_INVALID_END_TAG > <template>{{'</div>'}}</
|
|||
|
||||
exports[`compiler: parse > Errors > X_INVALID_END_TAG > <template>a </ b</template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -4252,7 +4252,7 @@ exports[`compiler: parse > Errors > X_INVALID_END_TAG > <template>a </ b</templa
|
|||
|
||||
exports[`compiler: parse > Errors > X_INVALID_END_TAG > <textarea></div></textarea> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -4322,7 +4322,7 @@ exports[`compiler: parse > Errors > X_INVALID_END_TAG > <textarea></div></textar
|
|||
|
||||
exports[`compiler: parse > Errors > X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END > <div v-foo:[sef fsef] /> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
|
@ -4446,7 +4446,7 @@ exports[`compiler: parse > Errors > X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END > <
|
|||
|
||||
exports[`compiler: parse > Errors > X_MISSING_END_TAG > <template><div> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -4521,7 +4521,7 @@ exports[`compiler: parse > Errors > X_MISSING_END_TAG > <template><div> 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > X_MISSING_END_TAG > <template><div></template> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -4596,7 +4596,7 @@ exports[`compiler: parse > Errors > X_MISSING_END_TAG > <template><div></templat
|
|||
|
||||
exports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > <div>{{ foo</div> 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
|
@ -4666,7 +4666,7 @@ exports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > <div>{{ foo</d
|
|||
|
||||
exports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > {{ 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"content": "{{",
|
||||
|
@ -4713,7 +4713,7 @@ exports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > {{ 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > {{ foo 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"content": "{{ foo",
|
||||
|
@ -4760,7 +4760,7 @@ exports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > {{ foo 1`] = `
|
|||
|
||||
exports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > {{}} 1`] = `
|
||||
{
|
||||
"cached": 0,
|
||||
"cached": [],
|
||||
"children": [
|
||||
{
|
||||
"content": {
|
||||
|
|
|
@ -1,37 +1,5 @@
|
|||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`scopeId compiler support > should push scopeId for hoisted nodes 1`] = `
|
||||
"import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from "vue"
|
||||
|
||||
const _withScopeId = n => (_pushScopeId("test"),n=n(),_popScopeId(),n)
|
||||
const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", -1 /* HOISTED */))
|
||||
const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", -1 /* HOISTED */))
|
||||
|
||||
export function render(_ctx, _cache) {
|
||||
return (_openBlock(), _createElementBlock("div", null, [
|
||||
_hoisted_1,
|
||||
_createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */),
|
||||
_hoisted_2
|
||||
]))
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`scopeId compiler support > should push typescript-compatible scopeId for hoisted nodes 1`] = `
|
||||
"import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from "vue"
|
||||
|
||||
const _withScopeId = (n: any) => (_pushScopeId("test"),n=n(),_popScopeId(),n)
|
||||
const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", -1 /* HOISTED */))
|
||||
const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", -1 /* HOISTED */))
|
||||
|
||||
export function render(_ctx: any,_cache: any) {
|
||||
return (_openBlock(), _createElementBlock("div", null, [
|
||||
_hoisted_1,
|
||||
_createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */),
|
||||
_hoisted_2
|
||||
]))
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`scopeId compiler support > should wrap default slot 1`] = `
|
||||
"import { createElementVNode as _createElementVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, openBlock as _openBlock, createBlock as _createBlock } from "vue"
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ function createRoot(options: Partial<RootNode> = {}): RootNode {
|
|||
directives: [],
|
||||
imports: [],
|
||||
hoists: [],
|
||||
cached: 0,
|
||||
cached: [],
|
||||
temps: 0,
|
||||
codegenNode: createSimpleExpression(`null`, false),
|
||||
loc: locStub,
|
||||
|
@ -267,7 +267,7 @@ describe('compiler: codegen', () => {
|
|||
disableTracking: true,
|
||||
props: undefined,
|
||||
children: createCallExpression(RENDER_LIST),
|
||||
patchFlag: '1',
|
||||
patchFlag: PatchFlags.TEXT,
|
||||
dynamicProps: undefined,
|
||||
directives: undefined,
|
||||
loc: locStub,
|
||||
|
@ -303,7 +303,7 @@ describe('compiler: codegen', () => {
|
|||
disableTracking: false,
|
||||
props: undefined,
|
||||
children: createCallExpression(RENDER_LIST),
|
||||
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT),
|
||||
patchFlag: PatchFlags.STABLE_FRAGMENT,
|
||||
dynamicProps: undefined,
|
||||
directives: undefined,
|
||||
loc: locStub,
|
||||
|
@ -364,7 +364,7 @@ describe('compiler: codegen', () => {
|
|||
),
|
||||
],
|
||||
// flag
|
||||
PatchFlags.FULL_PROPS + '',
|
||||
PatchFlags.FULL_PROPS,
|
||||
),
|
||||
}),
|
||||
)
|
||||
|
@ -375,7 +375,7 @@ describe('compiler: codegen', () => {
|
|||
[foo + bar]: bar
|
||||
}, [
|
||||
_${helperNameMap[CREATE_ELEMENT_VNODE]}("p", { "some-key": "foo" })
|
||||
], ${PatchFlags.FULL_PROPS})`)
|
||||
], ${genFlagText(PatchFlags.FULL_PROPS)})`)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
@ -422,7 +422,7 @@ describe('compiler: codegen', () => {
|
|||
test('CacheExpression', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
cached: 1,
|
||||
cached: [],
|
||||
codegenNode: createCacheExpression(
|
||||
1,
|
||||
createSimpleExpression(`foo`, false),
|
||||
|
@ -437,10 +437,10 @@ describe('compiler: codegen', () => {
|
|||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('CacheExpression w/ isVNode: true', () => {
|
||||
test('CacheExpression w/ isVOnce: true', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
cached: 1,
|
||||
cached: [],
|
||||
codegenNode: createCacheExpression(
|
||||
1,
|
||||
createSimpleExpression(`foo`, false),
|
||||
|
@ -456,7 +456,7 @@ describe('compiler: codegen', () => {
|
|||
`
|
||||
_cache[1] || (
|
||||
_setBlockTracking(-1),
|
||||
_cache[1] = foo,
|
||||
(_cache[1] = foo).cacheIndex = 1,
|
||||
_setBlockTracking(1),
|
||||
_cache[1]
|
||||
)
|
||||
|
@ -666,11 +666,14 @@ describe('compiler: codegen', () => {
|
|||
})
|
||||
|
||||
test('with patchFlag and no children/props', () => {
|
||||
expect(genCode(createVNodeCall(null, `"div"`, undefined, undefined, '1')))
|
||||
.toMatchInlineSnapshot(`
|
||||
"return _createElementVNode("div", null, null, 1)
|
||||
"
|
||||
`)
|
||||
expect(
|
||||
genCode(
|
||||
createVNodeCall(null, `"div"`, undefined, undefined, PatchFlags.TEXT),
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"return _createElementVNode("div", null, null, 1 /* TEXT */)
|
||||
"
|
||||
`)
|
||||
})
|
||||
|
||||
test('as block', () => {
|
||||
|
|
|
@ -1358,7 +1358,27 @@ describe('compiler: parse', () => {
|
|||
name: 'on',
|
||||
rawName: 'v-on.enter',
|
||||
arg: undefined,
|
||||
modifiers: ['enter'],
|
||||
modifiers: [
|
||||
{
|
||||
constType: 3,
|
||||
content: 'enter',
|
||||
isStatic: true,
|
||||
loc: {
|
||||
end: {
|
||||
column: 16,
|
||||
line: 1,
|
||||
offset: 15,
|
||||
},
|
||||
source: 'enter',
|
||||
start: {
|
||||
column: 11,
|
||||
line: 1,
|
||||
offset: 10,
|
||||
},
|
||||
},
|
||||
type: 4,
|
||||
},
|
||||
],
|
||||
exp: undefined,
|
||||
loc: {
|
||||
start: { offset: 5, line: 1, column: 6 },
|
||||
|
@ -1377,7 +1397,46 @@ describe('compiler: parse', () => {
|
|||
name: 'on',
|
||||
rawName: 'v-on.enter.exact',
|
||||
arg: undefined,
|
||||
modifiers: ['enter', 'exact'],
|
||||
modifiers: [
|
||||
{
|
||||
constType: 3,
|
||||
content: 'enter',
|
||||
isStatic: true,
|
||||
loc: {
|
||||
end: {
|
||||
column: 16,
|
||||
line: 1,
|
||||
offset: 15,
|
||||
},
|
||||
source: 'enter',
|
||||
start: {
|
||||
column: 11,
|
||||
line: 1,
|
||||
offset: 10,
|
||||
},
|
||||
},
|
||||
type: 4,
|
||||
},
|
||||
{
|
||||
constType: 3,
|
||||
content: 'exact',
|
||||
isStatic: true,
|
||||
loc: {
|
||||
end: {
|
||||
column: 22,
|
||||
line: 1,
|
||||
offset: 21,
|
||||
},
|
||||
source: 'exact',
|
||||
start: {
|
||||
column: 17,
|
||||
line: 1,
|
||||
offset: 16,
|
||||
},
|
||||
},
|
||||
type: 4,
|
||||
},
|
||||
],
|
||||
exp: undefined,
|
||||
loc: {
|
||||
start: { offset: 5, line: 1, column: 6 },
|
||||
|
@ -1406,7 +1465,46 @@ describe('compiler: parse', () => {
|
|||
source: 'click',
|
||||
},
|
||||
},
|
||||
modifiers: ['enter', 'exact'],
|
||||
modifiers: [
|
||||
{
|
||||
constType: 3,
|
||||
content: 'enter',
|
||||
isStatic: true,
|
||||
loc: {
|
||||
end: {
|
||||
column: 22,
|
||||
line: 1,
|
||||
offset: 21,
|
||||
},
|
||||
source: 'enter',
|
||||
start: {
|
||||
column: 17,
|
||||
line: 1,
|
||||
offset: 16,
|
||||
},
|
||||
},
|
||||
type: 4,
|
||||
},
|
||||
{
|
||||
constType: 3,
|
||||
content: 'exact',
|
||||
isStatic: true,
|
||||
loc: {
|
||||
end: {
|
||||
column: 28,
|
||||
line: 1,
|
||||
offset: 27,
|
||||
},
|
||||
source: 'exact',
|
||||
start: {
|
||||
column: 23,
|
||||
line: 1,
|
||||
offset: 22,
|
||||
},
|
||||
},
|
||||
type: 4,
|
||||
},
|
||||
],
|
||||
exp: undefined,
|
||||
loc: {
|
||||
start: { offset: 5, line: 1, column: 6 },
|
||||
|
@ -1435,7 +1533,27 @@ describe('compiler: parse', () => {
|
|||
source: '[a.b]',
|
||||
},
|
||||
},
|
||||
modifiers: ['camel'],
|
||||
modifiers: [
|
||||
{
|
||||
constType: 3,
|
||||
content: 'camel',
|
||||
isStatic: true,
|
||||
loc: {
|
||||
end: {
|
||||
column: 22,
|
||||
line: 1,
|
||||
offset: 21,
|
||||
},
|
||||
source: 'camel',
|
||||
start: {
|
||||
column: 17,
|
||||
line: 1,
|
||||
offset: 16,
|
||||
},
|
||||
},
|
||||
type: 4,
|
||||
},
|
||||
],
|
||||
exp: undefined,
|
||||
loc: {
|
||||
start: { offset: 5, line: 1, column: 6 },
|
||||
|
@ -1530,7 +1648,27 @@ describe('compiler: parse', () => {
|
|||
source: 'a',
|
||||
},
|
||||
},
|
||||
modifiers: ['prop'],
|
||||
modifiers: [
|
||||
{
|
||||
constType: 0,
|
||||
content: 'prop',
|
||||
isStatic: false,
|
||||
loc: {
|
||||
end: {
|
||||
column: 1,
|
||||
line: 1,
|
||||
offset: 0,
|
||||
},
|
||||
source: '',
|
||||
start: {
|
||||
column: 1,
|
||||
line: 1,
|
||||
offset: 0,
|
||||
},
|
||||
},
|
||||
type: 4,
|
||||
},
|
||||
],
|
||||
exp: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'b',
|
||||
|
@ -1569,7 +1707,27 @@ describe('compiler: parse', () => {
|
|||
source: 'a',
|
||||
},
|
||||
},
|
||||
modifiers: ['sync'],
|
||||
modifiers: [
|
||||
{
|
||||
constType: 3,
|
||||
content: 'sync',
|
||||
isStatic: true,
|
||||
loc: {
|
||||
end: {
|
||||
column: 13,
|
||||
line: 1,
|
||||
offset: 12,
|
||||
},
|
||||
source: 'sync',
|
||||
start: {
|
||||
column: 9,
|
||||
line: 1,
|
||||
offset: 8,
|
||||
},
|
||||
},
|
||||
type: 4,
|
||||
},
|
||||
],
|
||||
exp: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'b',
|
||||
|
@ -1649,7 +1807,27 @@ describe('compiler: parse', () => {
|
|||
source: 'a',
|
||||
},
|
||||
},
|
||||
modifiers: ['enter'],
|
||||
modifiers: [
|
||||
{
|
||||
constType: 3,
|
||||
content: 'enter',
|
||||
isStatic: true,
|
||||
loc: {
|
||||
end: {
|
||||
column: 14,
|
||||
line: 1,
|
||||
offset: 13,
|
||||
},
|
||||
source: 'enter',
|
||||
start: {
|
||||
column: 9,
|
||||
line: 1,
|
||||
offset: 8,
|
||||
},
|
||||
},
|
||||
type: 4,
|
||||
},
|
||||
],
|
||||
exp: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'b',
|
||||
|
@ -1841,6 +2019,21 @@ describe('compiler: parse', () => {
|
|||
children: [{ type: NodeTypes.TEXT, content: `{{ number ` }],
|
||||
},
|
||||
])
|
||||
|
||||
const ast3 = baseParse(`<div v-pre><textarea>{{ foo </textarea></div>`, {
|
||||
parseMode: 'html',
|
||||
})
|
||||
expect((ast3.children[0] as ElementNode).children).toMatchObject([
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
children: [
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: `{{ foo `,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
test('self-closing v-pre', () => {
|
||||
|
@ -2176,6 +2369,7 @@ describe('compiler: parse', () => {
|
|||
test('should remove leading newline character immediately following the pre element start tag', () => {
|
||||
const ast = parse(`<pre>\n foo bar </pre>`, {
|
||||
isPreTag: tag => tag === 'pre',
|
||||
isIgnoreNewlineTag: tag => tag === 'pre',
|
||||
})
|
||||
expect(ast.children).toHaveLength(1)
|
||||
const preElement = ast.children[0] as ElementNode
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import { baseCompile } from '../src/compile'
|
||||
import { POP_SCOPE_ID, PUSH_SCOPE_ID } from '../src/runtimeHelpers'
|
||||
import { PatchFlags } from '@vue/shared'
|
||||
import { genFlagText } from './testUtils'
|
||||
|
||||
/**
|
||||
* Ensure all slot functions are wrapped with _withCtx
|
||||
|
@ -57,53 +54,4 @@ describe('scopeId compiler support', () => {
|
|||
expect(code).toMatch(/name: i,\s+fn: _withCtx\(/)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('should push scopeId for hoisted nodes', () => {
|
||||
const { ast, code } = baseCompile(
|
||||
`<div><div>hello</div>{{ foo }}<div>world</div></div>`,
|
||||
{
|
||||
mode: 'module',
|
||||
scopeId: 'test',
|
||||
hoistStatic: true,
|
||||
},
|
||||
)
|
||||
expect(ast.helpers).toContain(PUSH_SCOPE_ID)
|
||||
expect(ast.helpers).toContain(POP_SCOPE_ID)
|
||||
expect(ast.hoists.length).toBe(2)
|
||||
;[
|
||||
`const _withScopeId = n => (_pushScopeId("test"),n=n(),_popScopeId(),n)`,
|
||||
`const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText(
|
||||
PatchFlags.HOISTED,
|
||||
)}))`,
|
||||
`const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText(
|
||||
PatchFlags.HOISTED,
|
||||
)}))`,
|
||||
].forEach(c => expect(code).toMatch(c))
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('should push typescript-compatible scopeId for hoisted nodes', () => {
|
||||
const { ast, code } = baseCompile(
|
||||
`<div><div>hello</div>{{ foo }}<div>world</div></div>`,
|
||||
{
|
||||
mode: 'module',
|
||||
scopeId: 'test',
|
||||
hoistStatic: true,
|
||||
isTS: true,
|
||||
},
|
||||
)
|
||||
expect(ast.helpers).toContain(PUSH_SCOPE_ID)
|
||||
expect(ast.helpers).toContain(POP_SCOPE_ID)
|
||||
expect(ast.hoists.length).toBe(2)
|
||||
;[
|
||||
`const _withScopeId = (n: any) => (_pushScopeId("test"),n=n(),_popScopeId(),n)`,
|
||||
`const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText(
|
||||
PatchFlags.HOISTED,
|
||||
)}))`,
|
||||
`const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText(
|
||||
PatchFlags.HOISTED,
|
||||
)}))`,
|
||||
].forEach(c => expect(code).toMatch(c))
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3,6 +3,8 @@ import {
|
|||
ElementTypes,
|
||||
Namespaces,
|
||||
NodeTypes,
|
||||
type Property,
|
||||
type SimpleExpressionNode,
|
||||
type VNodeCall,
|
||||
locStub,
|
||||
} from '../src'
|
||||
|
@ -22,7 +24,10 @@ const bracketsRE = /^\[|\]$/g
|
|||
// e.g.
|
||||
// - createObjectMatcher({ 'foo': '[bar]' }) matches { foo: bar }
|
||||
// - createObjectMatcher({ '[foo]': 'bar' }) matches { [foo]: "bar" }
|
||||
export function createObjectMatcher(obj: Record<string, any>) {
|
||||
export function createObjectMatcher(obj: Record<string, any>): {
|
||||
type: NodeTypes
|
||||
properties: Partial<Property>[]
|
||||
} {
|
||||
return {
|
||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||
properties: Object.keys(obj).map(key => ({
|
||||
|
@ -31,7 +36,7 @@ export function createObjectMatcher(obj: Record<string, any>) {
|
|||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: key.replace(bracketsRE, ''),
|
||||
isStatic: !leadingBracketRE.test(key),
|
||||
},
|
||||
} as SimpleExpressionNode,
|
||||
value: isString(obj[key])
|
||||
? {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
|
@ -78,7 +83,7 @@ type Flags = PatchFlags | ShapeFlags
|
|||
export function genFlagText(
|
||||
flag: Flags | Flags[],
|
||||
names: { [k: number]: string } = PatchFlagNames,
|
||||
) {
|
||||
): string {
|
||||
if (isArray(flag)) {
|
||||
let f = 0
|
||||
flag.forEach(ff => {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue