diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index fe5e82b04a4..11853cec30c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -30,7 +30,7 @@ body: description: | The easiest way to provide a reproduction is by showing the bug in [The SFC Playground](https://sfc.vuejs.org/). If it cannot be reproduced in the playground and requires a proper build setup, try [StackBlitz](https://vite.new/vue). - If neither of these are suitable, you can always provide a GitHub reporistory. + If neither of these are suitable, you can always provide a GitHub repository. The reproduction should be **minimal** - i.e. it should contain only the bare minimum amount of code needed to show the bug. See [Bug Reproduction Guidelines](https://github.com/vuejs/core/blob/main/.github/bug-repro-guidelines.md) for more details. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eadcd94f6d8..3128dd2cb4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,10 @@ on: pull_request: branches: - main + +permissions: + contents: read # to fetch code (actions/checkout) + jobs: unit-test: runs-on: ubuntu-latest diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index d9ea7a07f72..16c6c9c5c10 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -5,8 +5,12 @@ on: name: Create Release +permissions: {} jobs: build: + permissions: + contents: write # to create release (yyx990803/release-tag) + name: Create Release runs-on: ubuntu-latest steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 87ac185a7ef..af5bb244e1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,67 @@ +## [3.2.40](https://github.com/vuejs/core/compare/v3.2.39...v3.2.40) (2022-09-28) + + +### Bug Fixes + +* **compat:** list cjs dependencies for compat build ([96cd924](https://github.com/vuejs/core/commit/96cd924e440984a37e4759673f3c16921b69affe)), closes [#6602](https://github.com/vuejs/core/issues/6602) +* **compiler-dom:** remove v-bind boolean attribute with literal false value when stringifying ([#6635](https://github.com/vuejs/core/issues/6635)) ([6c6fe2c](https://github.com/vuejs/core/commit/6c6fe2c0cd89ce513503b1f85e0ddb696fd81e54)), closes [#6617](https://github.com/vuejs/core/issues/6617) +* **compiler-sfc:** fix expression check for v-on with object literal value ([#6652](https://github.com/vuejs/core/issues/6652)) ([6958ec1](https://github.com/vuejs/core/commit/6958ec1b37fb4a9244ae222a35fcac032d26ad8a)), closes [#6650](https://github.com/vuejs/core/issues/6650) [#6674](https://github.com/vuejs/core/issues/6674) +* **compilre-core:** dynamic v-on and static v-on should be merged ([#6747](https://github.com/vuejs/core/issues/6747)) ([f9d43b9](https://github.com/vuejs/core/commit/f9d43b99f83af7fc140938a1d8d2db89666fb4e1)), closes [#6742](https://github.com/vuejs/core/issues/6742) +* **runtime-core:** avoid hoisted vnodes retaining detached DOM nodes ([fc5bdb3](https://github.com/vuejs/core/commit/fc5bdb36ed429d6c3c956f373206ce75467adaf3)), closes [#6591](https://github.com/vuejs/core/issues/6591) +* **runtime-core:** Lifecycle hooks should support callbacks shared by reference ([#6687](https://github.com/vuejs/core/issues/6687)) ([c71a08e](https://github.com/vuejs/core/commit/c71a08e6fd44ee06c6b4f61d67727a7b7503605e)), closes [#6686](https://github.com/vuejs/core/issues/6686) +* **runtime-core:** remove prod-only hoisted clone behavior for manual DOM manipulation compat ([aa70188](https://github.com/vuejs/core/commit/aa70188c41fab1a4139748dd7b7c71532d063f3a)), closes [#6727](https://github.com/vuejs/core/issues/6727) [#6739](https://github.com/vuejs/core/issues/6739) +* **runtime-core:** unset removed props first in full diff mode ([c0d8db8](https://github.com/vuejs/core/commit/c0d8db81a636f0ad1e725b7c04608d3a211cf163)), closes [#6571](https://github.com/vuejs/core/issues/6571) +* **runtime-dom:** fix unnecessary warning when setting coerced dom property value ([b1817fe](https://github.com/vuejs/core/commit/b1817fe9eeb66a18f405ada9072149515654a9bd)), closes [#6616](https://github.com/vuejs/core/issues/6616) +* **ssr:** avoid ast.helpers duplication ([#6664](https://github.com/vuejs/core/issues/6664)) ([57ffc3e](https://github.com/vuejs/core/commit/57ffc3e546395ba048009396a4b82d3f968cca2c)) +* **ssr:** fix dynamic slot regression in ssr ([8963c55](https://github.com/vuejs/core/commit/8963c5508cde3a0c990b2748787ffb582b16f23f)), closes [#6651](https://github.com/vuejs/core/issues/6651) +* **ssr:** fix hydration mismatch when entire multi-root template is stringified ([9698dd3](https://github.com/vuejs/core/commit/9698dd3cf1dfdb95d4dc4b4f7bd24ff94b4b5d84)), closes [#6637](https://github.com/vuejs/core/issues/6637) +* **ssr:** fix pre tag windows newline hydration mismatch ([0382019](https://github.com/vuejs/core/commit/03820193a8f768293d665ca2753439fe73aed0fd)), closes [#6410](https://github.com/vuejs/core/issues/6410) +* **ssr:** respect case when rendering dynamic attrs on svg ([121eb32](https://github.com/vuejs/core/commit/121eb32fb0a21cf9988d788cfad1b4249b15997b)), closes [#6755](https://github.com/vuejs/core/issues/6755) + + + +## [3.2.39](https://github.com/vuejs/core/compare/v3.2.38...v3.2.39) (2022-09-08) + + +### Bug Fixes + +* **runtime-core:** avoid double firing when mounting inside a watcher callback ([6aaf8ef](https://github.com/vuejs/core/commit/6aaf8efefffdb0d4b93f178b2bb36cd3c6bc31b8)), closes [#6614](https://github.com/vuejs/core/issues/6614) +* **runtime-core:** support extends template for runtime compiler ([#6250](https://github.com/vuejs/core/issues/6250)) ([9875ecd](https://github.com/vuejs/core/commit/9875ecd762155732008e397d450edb0f8c01b05c)), closes [#6249](https://github.com/vuejs/core/issues/6249) +* **ssr:** reset current instance ([#6184](https://github.com/vuejs/core/issues/6184)) ([6493da5](https://github.com/vuejs/core/commit/6493da5bfa4624267248deb3d31dca2a4fb22aee)), closes [#6110](https://github.com/vuejs/core/issues/6110) +* **types:** support TypeScript 4.8 ([5381abc](https://github.com/vuejs/core/commit/5381abc0571e58a9be6cf482dc50c8db8300f86c)), closes [#6554](https://github.com/vuejs/core/issues/6554) + + + +## [3.2.38](https://github.com/vuejs/core/compare/v3.2.37...v3.2.38) (2022-08-30) + + +### Bug Fixes + +* **compiler-sfc:** fix template usage check edge case for v-on statements ([769e555](https://github.com/vuejs/core/commit/769e5555f9d9004ce541613341652db859881570)) +* **compiler-sfc:** only add decorators-legacy parser plugin when new decorators plugin is not used ([3ff8369](https://github.com/vuejs/core/commit/3ff83694f523e3fe148d22a469ed742b46603bb4)) +* **compiler-sfc:** rewriteDefault for class with decorators ([#6320](https://github.com/vuejs/core/issues/6320)) ([81a7819](https://github.com/vuejs/core/commit/81a7819535c4382ba7817c817722bac6d41921d8)), closes [#6318](https://github.com/vuejs/core/issues/6318) +* **custom-element:** fix event listeners with capital letter event names on custom elements ([0739f89](https://github.com/vuejs/core/commit/0739f8909a0e56ae0fa760f233dfb8c113c9bde2)) +* **hmr:** fix HMR for nested non-SFC components ([#4077](https://github.com/vuejs/core/issues/4077)) ([96eb745](https://github.com/vuejs/core/commit/96eb7452548293c343613ab778248a5da9619f45)) +* **reactivity:** fix shallow/readonly edge cases ([a95554d](https://github.com/vuejs/core/commit/a95554d35c65e5bfd0bf9d1c5b908ae789345a6d)) +* **runtime-core:** only set cache for object keys ([#6266](https://github.com/vuejs/core/issues/6266)) ([c3465c1](https://github.com/vuejs/core/commit/c3465c1e889651df925324ed2a10ac2d5f229110)) +* **slots:** ensure different branches of dynamic slots have different keys ([00036bb](https://github.com/vuejs/core/commit/00036bb52c4e641b2be7fa55c39ced9448163b0f)), closes [#6202](https://github.com/vuejs/core/issues/6202) +* **ssr:** forward helpers provided by CSS `v-bind` ([#6489](https://github.com/vuejs/core/issues/6489)) ([2024d11](https://github.com/vuejs/core/commit/2024d11db03d9c6e49e20b3355f3df0ba04bb834)), closes [#6201](https://github.com/vuejs/core/issues/6201) +* **types:** add types field for sub package exports ([c1ee6ca](https://github.com/vuejs/core/commit/c1ee6caa82da89b3a9c33e2253c07a681ebb2628)) +* **types:** fix on* props incorrect type for TS 4.7 ([#6216](https://github.com/vuejs/core/issues/6216)) ([8dcb6c7](https://github.com/vuejs/core/commit/8dcb6c7bbdd2905469e2bb11dfff27b58cc784b2)), closes [#6052](https://github.com/vuejs/core/issues/6052) +* **watch:** flush:pre watchers should not fire if state change causes ([78c199d](https://github.com/vuejs/core/commit/78c199d6dbe8931520b75d8bfe0d49366a06922a)), closes [#2291](https://github.com/vuejs/core/issues/2291) + + +### Features + +* **custom-elements:** automatically respect custom elements when compiling in browser ([9f8f07e](https://github.com/vuejs/core/commit/9f8f07ed38b2e003f308875fe3a3e4c0d5477b32)) + + +### Performance Improvements + +* **ssr:** improve isComment check ([#6078](https://github.com/vuejs/core/issues/6078)) ([25f7a16](https://github.com/vuejs/core/commit/25f7a16a6eccbfa8d857977dcf1f23fb36b830b5)) + + + ## [3.2.37](https://github.com/vuejs/core/compare/v3.2.36...v3.2.37) (2022-06-06) diff --git a/README.md b/README.md index 0742b381303..8d2342c1ea0 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,19 @@ Please follow the documentation at [vuejs.org](https://vuejs.org/)! Vue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of these awesome [backers](https://github.com/vuejs/core/blob/main/BACKERS.md). If you'd like to join them, please consider [ sponsor Vue's development](https://vuejs.org/sponsor/). +
+
+ + + +
+ diff --git a/package.json b/package.json index bcdb9b60675..aeff54e501e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "3.2.37", + "version": "3.2.40", "packageManager": "pnpm@7.1.0", "scripts": { "dev": "node scripts/dev.js", @@ -51,7 +51,7 @@ "devDependencies": { "@babel/types": "^7.12.0", "@esbuild-plugins/node-modules-polyfill": "^0.1.4", - "@microsoft/api-extractor": "^7.15.1", + "@microsoft/api-extractor": "~7.20.0", "@rollup/plugin-commonjs": "^18.0.0", "@rollup/plugin-json": "^4.0.0", "@rollup/plugin-node-resolve": "^11.2.1", @@ -93,8 +93,8 @@ "todomvc-app-css": "^2.3.0", "ts-jest": "^27.0.5", "tslib": "^2.4.0", - "typescript": "^4.7.4", - "vite": "^2.9.8", + "typescript": "^4.8.0", + "vite": "^3.0.0", "vue": "workspace:*", "yorkie": "^2.0.0" } diff --git a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap index a250f325d0a..826bc4a027f 100644 --- a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap @@ -43,7 +43,8 @@ export function render(_ctx, _cache) { name: \\"foo\\", fn: _withCtx(() => [ _createElementVNode(\\"div\\") - ]) + ]), + key: \\"0\\" } : undefined, _renderList(_ctx.list, (i) => { diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap index 967f2b3f45e..55796020a47 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap @@ -56,7 +56,8 @@ return function render(_ctx, _cache) { (_ctx.ok) ? { name: \\"one\\", - fn: _withCtx((props) => [_toDisplayString(props)]) + fn: _withCtx((props) => [_toDisplayString(props)]), + key: \\"0\\" } : undefined ]), 1024 /* DYNAMIC_SLOTS */)) @@ -76,16 +77,19 @@ return function render(_ctx, _cache) { ok ? { name: \\"one\\", - fn: _withCtx(() => [\\"foo\\"]) + fn: _withCtx(() => [\\"foo\\"]), + key: \\"0\\" } : orNot ? { name: \\"two\\", - fn: _withCtx((props) => [\\"bar\\"]) + fn: _withCtx((props) => [\\"bar\\"]), + key: \\"1\\" } : { name: \\"one\\", - fn: _withCtx(() => [\\"baz\\"]) + fn: _withCtx(() => [\\"baz\\"]), + key: \\"2\\" } ]), 1024 /* DYNAMIC_SLOTS */)) } @@ -105,7 +109,8 @@ return function render(_ctx, _cache) { ok ? { name: \\"one\\", - fn: _withCtx(() => [\\"hello\\"]) + fn: _withCtx(() => [\\"hello\\"]), + key: \\"0\\" } : undefined ]), 1024 /* DYNAMIC_SLOTS */)) diff --git a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts index 2c4421aeb3b..eec5a76d363 100644 --- a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts +++ b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts @@ -13,7 +13,6 @@ import { import { FRAGMENT, RENDER_LIST, - CREATE_TEXT, NORMALIZE_CLASS } from '../../src/runtimeHelpers' import { transformElement } from '../../src/transforms/transformElement' @@ -378,36 +377,6 @@ describe('compiler: hoistStatic transform', () => { expect(generate(root).code).toMatchSnapshot() }) - test('hoist static text node between elements', () => { - const root = transformWithHoist(`: + // in SSR, browsers normalize server-rendered \r\n into a single \n + // in the DOM + node.content = node.content.replace(/\r\n/g, '\n') } } // Remove comment nodes if desired by configuration. diff --git a/packages/compiler-core/src/transforms/hoistStatic.ts b/packages/compiler-core/src/transforms/hoistStatic.ts index 848052581ed..b2b7f871c0a 100644 --- a/packages/compiler-core/src/transforms/hoistStatic.ts +++ b/packages/compiler-core/src/transforms/hoistStatic.ts @@ -97,12 +97,6 @@ function walk( } } } - } else if ( - child.type === NodeTypes.TEXT_CALL && - getConstantType(child.content, context) >= ConstantTypes.CAN_HOIST - ) { - child.codegenNode = context.hoist(child.codegenNode) - hoistedCount++ } // walk further diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 2d15227f70f..7b53b24822c 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -413,6 +413,16 @@ export function buildProps( let hasVnodeHook = false const dynamicPropNames: string[] = [] + const pushMergeArg = (arg?: PropsExpression) => { + if (properties.length) { + mergeArgs.push( + createObjectExpression(dedupeProperties(properties), elementLoc) + ) + properties = [] + } + if (arg) mergeArgs.push(arg) + } + const analyzePatchFlag = ({ key, value }: Property) => { if (isStaticExp(key)) { const name = key.content @@ -590,13 +600,9 @@ export function buildProps( if (!arg && (isVBind || isVOn)) { hasDynamicKeys = true if (exp) { - if (properties.length) { - mergeArgs.push( - createObjectExpression(dedupeProperties(properties), elementLoc) - ) - properties = [] - } if (isVBind) { + // have to merge early for compat build check + pushMergeArg() if (__COMPAT__) { // 2.x v-bind object order compat if (__DEV__) { @@ -643,11 +649,11 @@ export function buildProps( mergeArgs.push(exp) } else { // v-on="obj" -> toHandlers(obj) - mergeArgs.push({ + pushMergeArg({ type: NodeTypes.JS_CALL_EXPRESSION, loc, callee: context.helper(TO_HANDLERS), - arguments: [exp] + arguments: isComponent ? [exp] : [exp, `true`] }) } } else { @@ -668,7 +674,11 @@ export function buildProps( // has built-in directive transform. const { props, needRuntime } = directiveTransform(prop, node, context) !ssr && props.forEach(analyzePatchFlag) - properties.push(...props) + if (isVOn && arg && !isStaticExp(arg)) { + pushMergeArg(createObjectExpression(props, elementLoc)) + } else { + properties.push(...props) + } if (needRuntime) { runtimeDirectives.push(prop) if (isSymbol(needRuntime)) { @@ -691,11 +701,8 @@ export function buildProps( // has v-bind="object" or v-on="object", wrap with mergeProps if (mergeArgs.length) { - if (properties.length) { - mergeArgs.push( - createObjectExpression(dedupeProperties(properties), elementLoc) - ) - } + // close up any not-yet-merged props + pushMergeArg() if (mergeArgs.length > 1) { propsExpression = createCallExpression( context.helper(MERGE_PROPS), diff --git a/packages/compiler-core/src/transforms/vOn.ts b/packages/compiler-core/src/transforms/vOn.ts index 060a7ef9097..a9dfe77eff7 100644 --- a/packages/compiler-core/src/transforms/vOn.ts +++ b/packages/compiler-core/src/transforms/vOn.ts @@ -47,12 +47,17 @@ export const transformOn: DirectiveTransform = ( if (rawName.startsWith('vue:')) { rawName = `vnode-${rawName.slice(4)}` } - // for all event listeners, auto convert it to camelCase. See issue #2249 - eventName = createSimpleExpression( - toHandlerKey(camelize(rawName)), - true, - arg.loc - ) + const eventString = + node.tagType === ElementTypes.COMPONENT || + rawName.startsWith('vnode') || + !/[A-Z]/.test(rawName) + ? // for component and vnode lifecycle event listeners, auto convert + // it to camelCase. See issue #2249 + toHandlerKey(camelize(rawName)) + // preserve case for plain element listeners that have uppercase + // letters, as these may be custom elements' custom events + : `on:${rawName}` + eventName = createSimpleExpression(eventString, true, arg.loc) } else { // #2388 eventName = createCompoundExpression([ diff --git a/packages/compiler-core/src/transforms/vSlot.ts b/packages/compiler-core/src/transforms/vSlot.ts index 8fc86740eb6..c4416dd45f7 100644 --- a/packages/compiler-core/src/transforms/vSlot.ts +++ b/packages/compiler-core/src/transforms/vSlot.ts @@ -160,6 +160,7 @@ export function buildSlots( let hasNamedDefaultSlot = false const implicitDefaultChildren: TemplateChildNode[] = [] const seenSlotNames = new Set() + let conditionalBranchIndex = 0 for (let i = 0; i < children.length; i++) { const slotElement = children[i] @@ -210,7 +211,7 @@ export function buildSlots( dynamicSlots.push( createConditionalExpression( vIf.exp!, - buildDynamicSlot(slotName, slotFunction), + buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++), defaultFallback ) ) @@ -243,10 +244,14 @@ export function buildSlots( conditional.alternate = vElse.exp ? createConditionalExpression( vElse.exp, - buildDynamicSlot(slotName, slotFunction), + buildDynamicSlot( + slotName, + slotFunction, + conditionalBranchIndex++ + ), defaultFallback ) - : buildDynamicSlot(slotName, slotFunction) + : buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++) } else { context.onError( createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, vElse.loc) @@ -369,12 +374,19 @@ export function buildSlots( function buildDynamicSlot( name: ExpressionNode, - fn: FunctionExpression + fn: FunctionExpression, + index?: number ): ObjectExpression { - return createObjectExpression([ + const props = [ createObjectProperty(`name`, name), createObjectProperty(`fn`, fn) - ]) + ] + if (index != null) { + props.push( + createObjectProperty(`key`, createSimpleExpression(String(index), true)) + ) + } + return createObjectExpression(props) } function hasForwardedSlots(children: TemplateChildNode[]): boolean { diff --git a/packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts b/packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts index c737071a827..bedec9fc00a 100644 --- a/packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts @@ -410,6 +410,29 @@ describe('stringify static html', () => { }) }) + // #6617 + test('should remove boolean attribute for `false`', () => { + const { ast } = compileWithStringify( + `${repeat( + ``, + StringifyThresholds.NODE_COUNT + )}` + ) + expect(ast.hoists[0]).toMatchObject({ + type: NodeTypes.JS_CALL_EXPRESSION, + callee: CREATE_STATIC, + arguments: [ + JSON.stringify( + `${repeat( + ``, + StringifyThresholds.NODE_COUNT + )}` + ), + '21' + ] + }) + }) + test('should stringify svg', () => { const svg = `