From e0428884b57ac834274045bd33841263aeae259e Mon Sep 17 00:00:00 2001 From: LiuSeen <91084928+liuseen-l@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:10:01 +0800 Subject: [PATCH 01/10] fix(defineModel): detect changes respect custom getter and setter (#11543) fix: #11541 fix: #11526 close: #11527 --- .../__tests__/helpers/useModel.spec.ts | 92 +++++++++++++++++++ packages/runtime-core/src/helpers/useModel.ts | 5 +- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/helpers/useModel.spec.ts b/packages/runtime-core/__tests__/helpers/useModel.spec.ts index 4c30de2f26a..3c724b0ba00 100644 --- a/packages/runtime-core/__tests__/helpers/useModel.spec.ts +++ b/packages/runtime-core/__tests__/helpers/useModel.spec.ts @@ -657,4 +657,96 @@ describe('useModel', () => { expect(setValue).toBeCalledTimes(2) expect(msg.value).toBe(defaultVal) }) + + // #11526 + test('custom getter', () => { + let changeChildMsg!: (val: boolean) => void + const getter = (value: boolean) => !value + + const Comp = defineComponent({ + props: ['msg'], + emits: ['update:msg'], + setup(props) { + const childMsg = useModel(props, 'msg', { + get: getter, + set: value => !value, + }) + changeChildMsg = (val: boolean) => (childMsg.value = val) + return () => { + return childMsg.value + } + }, + }) + + const defaultVal = false + const msg = ref(defaultVal) + const Parent = defineComponent({ + setup() { + return () => + h(Comp, { + msg: msg.value, + 'onUpdate:msg': val => { + msg.value = val + }, + }) + }, + }) + + const root = nodeOps.createElement('div') + render(h(Parent), root) + + changeChildMsg(!getter(msg.value)) + expect(msg.value).toBe(true) + + changeChildMsg(!getter(msg.value)) + expect(msg.value).toBe(false) + }) + + // #11541 + test('custom setter', () => { + let changeChildMsg!: (val: boolean) => void + + const Comp = defineComponent({ + props: ['msg'], + emits: ['update:msg'], + setup(props) { + const childMsg = useModel(props, 'msg', { + set: value => { + if (value === msg.value) { + return null + } else { + return value + } + }, + }) + changeChildMsg = (val: boolean) => (childMsg.value = val) + return () => { + return childMsg.value + } + }, + }) + + const defaultVal = false + const msg = ref(defaultVal) + const Parent = defineComponent({ + setup() { + return () => + h(Comp, { + msg: msg.value, + 'onUpdate:msg': val => { + msg.value = val + }, + }) + }, + }) + + const root = nodeOps.createElement('div') + render(h(Parent), root) + + changeChildMsg(true) + expect(msg.value).toBe(true) + + changeChildMsg(true) + expect(msg.value).toBe(null) + }) }) diff --git a/packages/runtime-core/src/helpers/useModel.ts b/packages/runtime-core/src/helpers/useModel.ts index 5bcd316931d..8180fb32c47 100644 --- a/packages/runtime-core/src/helpers/useModel.ts +++ b/packages/runtime-core/src/helpers/useModel.ts @@ -51,8 +51,9 @@ export function useModel( }, set(value) { + const emittedValue = options.set ? options.set(value) : value if ( - !hasChanged(value, localValue) && + !hasChanged(emittedValue, localValue) && !(prevSetValue !== EMPTY_OBJ && hasChanged(value, prevSetValue)) ) { return @@ -74,7 +75,7 @@ export function useModel( localValue = value trigger() } - const emittedValue = options.set ? options.set(value) : value + i.emit(`update:${name}`, emittedValue) // #10279: if the local value is converted via a setter but the value // emitted to parent was the same, the parent will not trigger any From 29e4a1109a8d2a70eec9beda873fde2f4cac5a5b Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 7 Aug 2024 22:31:31 +0800 Subject: [PATCH 02/10] workflow: force fetch all tags in release action --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fcf0c3fac51..350245d3b45 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,6 +43,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ inputs.branch }} + fetch-depth: 0 # need this to get tags for changelog generation - name: Install pnpm uses: pnpm/action-setup@v4 From 236fb7abebe567b73826a3ddc2120f3273377ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=B1=E5=90=B9=E8=89=B2=E5=BE=A1=E5=AE=88?= <85992002+KazariEX@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:13:24 +0800 Subject: [PATCH 03/10] fix(compiler-core): use `isProp.arg.loc` instead of `isProp.loc` (#11547) --- packages/compiler-core/src/transforms/transformElement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index ebaf08375b9..e40280bd1ff 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -250,7 +250,7 @@ export function resolveComponentType( exp = isProp.exp if (!exp) { // #10469 handle :is shorthand - exp = createSimpleExpression(`is`, false, isProp.loc) + exp = createSimpleExpression(`is`, false, isProp.arg!.loc) if (!__BROWSER__) { exp = isProp.exp = processExpression(exp, context) } From 32a1433e0debd538c199bde18390bb903b4cde5a Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 8 Aug 2024 18:06:32 +0800 Subject: [PATCH 04/10] workflow: fix size report base branch --- .github/workflows/size-data.yml | 12 ++++++++---- .github/workflows/size-report.yml | 16 +++++++++++----- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/.github/workflows/size-data.yml b/.github/workflows/size-data.yml index 664f75aeeca..f73a59607af 100644 --- a/.github/workflows/size-data.yml +++ b/.github/workflows/size-data.yml @@ -43,12 +43,16 @@ jobs: name: size-data path: temp/size - - name: Save PR number + - name: Save PR number & base branch if: ${{github.event_name == 'pull_request'}} - run: echo ${{ github.event.number }} > ./pr.txt + run: | + echo ${{ github.event.number }} > ./number.txt + echo ${{ github.base_ref }} > ./base.txt - uses: actions/upload-artifact@v4 if: ${{github.event_name == 'pull_request'}} with: - name: pr-number - path: pr.txt + name: pr-info + path: | + number.txt + base.txt diff --git a/.github/workflows/size-report.yml b/.github/workflows/size-report.yml index 25c93d8ed04..c8258f8b920 100644 --- a/.github/workflows/size-report.yml +++ b/.github/workflows/size-report.yml @@ -35,18 +35,24 @@ jobs: - name: Install dependencies run: pnpm install - - name: Download PR number + - name: Download PR info uses: dawidd6/action-download-artifact@v6 with: - name: pr-number + name: pr-info run_id: ${{ github.event.workflow_run.id }} - path: /tmp/pr-number + path: /tmp/pr-info - name: Read PR Number id: pr-number uses: juliangruber/read-file-action@v1 with: - path: /tmp/pr-number/pr.txt + path: /tmp/pr-info/number.txt + + - name: Read PR base branch + id: pr-base + uses: juliangruber/read-file-action@v1 + with: + path: /tmp/pr-info/base.txt - name: Download Size Data uses: dawidd6/action-download-artifact@v6 @@ -58,7 +64,7 @@ jobs: - name: Download Previous Size Data uses: dawidd6/action-download-artifact@v6 with: - branch: ${{ github.base_ref }} + branch: ${{ steps.pr-base.outputs.content }} workflow: size-data.yml event: push name: size-data From 47cdf241f23d7836f9c646dc82a4d38540c0dece Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 8 Aug 2024 20:44:35 +0800 Subject: [PATCH 05/10] workflow: adjust release workflow --- .github/workflows/canary-minor.yml | 2 +- .github/workflows/canary.yml | 2 +- .github/workflows/release-gh.yml | 28 ----- .github/workflows/release.yml | 60 ++-------- scripts/release.js | 172 +++++++++++++++++------------ 5 files changed, 113 insertions(+), 151 deletions(-) delete mode 100644 .github/workflows/release-gh.yml diff --git a/.github/workflows/canary-minor.yml b/.github/workflows/canary-minor.yml index ffb9b384d4e..b5d75b9cebb 100644 --- a/.github/workflows/canary-minor.yml +++ b/.github/workflows/canary-minor.yml @@ -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 }} diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index a9432ced059..bb622725aa8 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -26,6 +26,6 @@ jobs: - run: pnpm install - - run: pnpm release --canary + - run: pnpm release --canary --publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release-gh.yml b/.github/workflows/release-gh.yml deleted file mode 100644 index f0cc5601ff9..00000000000 --- a/.github/workflows/release-gh.yml +++ /dev/null @@ -1,28 +0,0 @@ -on: - push: - tags: - - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 - -name: Create GH Release for Tag - -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. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 350245d3b45..d1ffa668d8c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,32 +1,9 @@ name: Release on: - workflow_dispatch: - inputs: - branch: - description: 'Branch to publish' - required: true - default: 'main' - type: choice - options: - - main - - minor - bump: - description: 'Bump version' - required: true - default: 'patch' - type: choice - options: - - patch - - minor - - prepatch - - preminor - - custom - custom_version: - description: 'Custom version' - required: false - default: '' - type: string + push: + tags: + - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 jobs: release: @@ -41,9 +18,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - ref: ${{ inputs.branch }} - fetch-depth: 0 # need this to get tags for changelog generation - name: Install pnpm uses: pnpm/action-setup@v4 @@ -58,38 +32,20 @@ jobs: - name: Install deps run: pnpm install - - name: Configure git user as vue bot - run: | - git config user.name "vue-bot" - git config user.email "" - - - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@v6 - with: - gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} - passphrase: ${{ secrets.GPG_PASSPHRASE }} - git_user_signingkey: true - git_commit_gpgsign: true - - - name: Run release script - id: release + - name: Build and publish + id: publish run: | - pnpm release ${{ inputs.bump != 'custom' && inputs.bump || inputs.custom_version }} --skipPrompts - RELEASE_TAG=$(git describe --tags --abbrev=0) - echo "tag=$RELEASE_TAG" >> $GITHUB_OUTPUT + pnpm release --publishOnly env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: Push tags - run: git push -u origin ${{ inputs.branch }} --follow-tags - - - name: Create Release for Tag + - name: Create GitHub release id: release_tag uses: yyx990803/release-tag@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: ${{ steps.release.outputs.tag }} + 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. diff --git a/scripts/release.js b/scripts/release.js index a85ee866ec3..a3517c30728 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -51,6 +51,13 @@ const { values: args, positionals } = parseArgs({ skipPrompts: { type: 'boolean', }, + publish: { + type: 'boolean', + default: false, + }, + publishOnly: { + type: 'boolean', + }, }, }) @@ -247,41 +254,7 @@ async function main() { } } - if (!skipTests) { - step('Checking CI status for HEAD...') - let isCIPassed = await getCIResult() - skipTests ||= isCIPassed - - if (isCIPassed) { - if (!skipPrompts) { - /** @type {{ yes: boolean }} */ - const { yes: promptSkipTests } = await prompt({ - type: 'confirm', - name: 'yes', - message: `CI for this commit passed. Skip local tests?`, - }) - skipTests = promptSkipTests - } else { - skipTests = true - } - } else if (skipPrompts) { - throw new Error( - 'CI for the latest commit has not passed yet. ' + - 'Only run the release workflow after the CI has passed.', - ) - } - } - - if (!skipTests) { - step('\nRunning tests...') - if (!isDryRun) { - await run('pnpm', ['run', 'test', '--run']) - } else { - console.log(`Skipped (dry run)`) - } - } else { - step('Tests skipped.') - } + await runTestsIfNeeded() // update all package versions and inter-dependencies step('\nUpdating cross dependencies...') @@ -291,16 +264,6 @@ async function main() { ) versionUpdated = true - // build all packages with types - step('\nBuilding all packages...') - if (!skipBuild && !isDryRun) { - await run('pnpm', ['run', 'build', '--withTypes']) - step('\nTesting built types...') - await run('pnpm', ['test-dts-only']) - } else { - console.log(`(skipped)`) - } - // generate changelog step('\nGenerating changelog...') await run(`pnpm`, ['run', 'changelog']) @@ -337,29 +300,15 @@ async function main() { } // publish packages - step('\nPublishing packages...') - - const additionalPublishFlags = [] - if (isDryRun) { - additionalPublishFlags.push('--dry-run') - } - if (isDryRun || skipGit) { - additionalPublishFlags.push('--no-git-checks') - } - // bypass the pnpm --publish-branch restriction which isn't too useful to us - // otherwise it leads to a prompt and blocks the release script - const branch = await getBranch() - if (branch !== 'main') { - additionalPublishFlags.push('--publish-branch', branch) - } - // add provenance metadata when releasing from CI - // canary release commits are not pushed therefore we don't need to add provenance - if (process.env.CI && !isCanary) { - additionalPublishFlags.push('--provenance') - } - - for (const pkg of packages) { - await publishPackage(pkg, targetVersion, additionalPublishFlags) + if (args.publish) { + await buildPackages() + await publishPackages(targetVersion) + } else { + console.log( + pico.yellow( + '\nPublish step skipped (will be done in GitHub actions on successful push)', + ), + ) } // push to GitHub @@ -386,6 +335,44 @@ async function main() { console.log() } +async function runTestsIfNeeded() { + if (!skipTests) { + step('Checking CI status for HEAD...') + let isCIPassed = await getCIResult() + skipTests ||= isCIPassed + + if (isCIPassed) { + if (!skipPrompts) { + /** @type {{ yes: boolean }} */ + const { yes: promptSkipTests } = await prompt({ + type: 'confirm', + name: 'yes', + message: `CI for this commit passed. Skip local tests?`, + }) + skipTests = promptSkipTests + } else { + skipTests = true + } + } else if (skipPrompts) { + throw new Error( + 'CI for the latest commit has not passed yet. ' + + 'Only run the release workflow after the CI has passed.', + ) + } + } + + if (!skipTests) { + step('\nRunning tests...') + if (!isDryRun) { + await run('pnpm', ['run', 'test', '--run']) + } else { + console.log(`Skipped (dry run)`) + } + } else { + step('Tests skipped.') + } +} + async function getCIResult() { try { const sha = await getSha() @@ -492,6 +479,46 @@ function updateDeps(pkg, depType, version, getNewPackageName) { }) } +async function buildPackages() { + step('\nBuilding all packages...') + if (!skipBuild) { + await run('pnpm', ['run', 'build', '--withTypes']) + } else { + console.log(`(skipped)`) + } +} + +/** + * @param {string} version + */ +async function publishPackages(version) { + // publish packages + step('\nPublishing packages...') + + const additionalPublishFlags = [] + if (isDryRun) { + additionalPublishFlags.push('--dry-run') + } + if (isDryRun || skipGit) { + additionalPublishFlags.push('--no-git-checks') + } + // bypass the pnpm --publish-branch restriction which isn't too useful to us + // otherwise it leads to a prompt and blocks the release script + const branch = await getBranch() + if (branch !== 'main') { + additionalPublishFlags.push('--publish-branch', branch) + } + // add provenance metadata when releasing from CI + // canary release commits are not pushed therefore we don't need to add provenance + if (process.env.CI && !isCanary) { + additionalPublishFlags.push('--provenance') + } + + for (const pkg of packages) { + await publishPackage(pkg, version, additionalPublishFlags) + } +} + /** * @param {string} pkgName * @param {string} version @@ -541,7 +568,14 @@ async function publishPackage(pkgName, version, additionalFlags) { } } -main().catch(err => { +async function publishOnly() { + await buildPackages() + await publishPackages(currentVersion) +} + +const fnToRun = args.publishOnly ? publishOnly : main + +fnToRun().catch(err => { if (versionUpdated) { // revert to current version on failed releases updateVersions(currentVersion) From f8ce86bad7bde895605349cbf62fb1ec18b0d745 Mon Sep 17 00:00:00 2001 From: LiuSeen <91084928+liuseen-l@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:07:57 +0800 Subject: [PATCH 06/10] chore(playground): support copying vue version (#11558) --- packages/sfc-playground/src/VersionSelect.vue | 28 +++++++++++++++++++ packages/sfc-playground/src/icons/Copy.vue | 14 ++++++++++ 2 files changed, 42 insertions(+) create mode 100644 packages/sfc-playground/src/icons/Copy.vue diff --git a/packages/sfc-playground/src/VersionSelect.vue b/packages/sfc-playground/src/VersionSelect.vue index bd24ac21a9e..3a30e497f97 100644 --- a/packages/sfc-playground/src/VersionSelect.vue +++ b/packages/sfc-playground/src/VersionSelect.vue @@ -1,5 +1,6 @@