Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ssr): v-slot stop empty attribute producing syntax error #3326

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6958ec1
fix(compiler-sfc): fix expression check for v-on with object literal …
godxiaoji Sep 27, 2022
121eb32
fix(ssr): respect case when rendering dynamic attrs on svg
yyx990803 Sep 27, 2022
0382019
fix(ssr): fix pre tag windows newline hydration mismatch
yyx990803 Sep 28, 2022
9698dd3
fix(ssr): fix hydration mismatch when entire multi-root template is s…
yyx990803 Sep 28, 2022
8963c55
fix(ssr): fix dynamic slot regression in ssr
yyx990803 Sep 28, 2022
3cc8e02
test(slots): ensure createSlots helper work with ssr slots (#6660)
shigma Sep 28, 2022
05c7b0d
ci: GitHub workflows security hardening (#6743)
sashashura Sep 28, 2022
cae1aa8
chore: use stricter slots type in createSlots
yyx990803 Sep 28, 2022
f9d43b9
fix(compilre-core): dynamic v-on and static v-on should be merged (#6…
Dunqing Sep 28, 2022
f402d41
refactor(compiler-core): extract props merging helper
yyx990803 Sep 28, 2022
96cd924
fix(compat): list cjs dependencies for compat build
yyx990803 Sep 28, 2022
551f606
release: v3.2.40
yyx990803 Sep 28, 2022
24f4c47
fix(devtools): avoid memory leak caused by devtools event buffer
yyx990803 Sep 28, 2022
534593c
chore: format
antfu Oct 3, 2022
3a13074
chore: eslint rules overrides (#6729)
PengBoUESTC Oct 3, 2022
a9e3fa4
refactor(types): improve of type assertion (#4177)
webfansplz Oct 3, 2022
8241749
types: creating Teleport with h and RawSlots #2613 (#2614)
edison1105 Oct 3, 2022
35a113e
fix(devtools): use cleanupBuffer instead of modifying _buffer (#6812)
posva Oct 3, 2022
45782df
chore: add cache for prettier and eslint (#6813)
sxzz Oct 4, 2022
c454aa5
chore: more pr tips in contribution guide [ci skip]
yyx990803 Oct 5, 2022
82e3f2d
chore: symbols as helperNameMap index type (#6622)
4xii Oct 5, 2022
35dc2bb
build: enforce LF line break for built files
yyx990803 Oct 11, 2022
a71f9ac
fix(effectScope): calling off() of a detached scope should not break …
yyx990803 Oct 14, 2022
5ee4053
fix(runtime-dom): fix event timestamp check in iframes
yyx990803 Oct 14, 2022
82a73da
fix(runtime-core): ensure that errors in slot function execution do n…
javastation Oct 14, 2022
9ae796d
fix(runtime-core): fix v-for ref reactivity behavior difference betwe…
baiwusanyu-c Oct 14, 2022
9617dd4
release: v3.2.41
yyx990803 Oct 14, 2022
bc167b5
fix(runtime-core): watching multiple values - handle `undefined` as i…
LinusBorg Oct 20, 2022
e5fc7dc
fix(types): ensure createBlock() helper accepts Teleport and Supsense…
LinusBorg Oct 20, 2022
e6224f4
fix(reactivity): enable trigger when use str to set length of arr (#6…
bcq028 Oct 21, 2022
54b6ba3
fix(runtime-core): ensure props definition objects are not mutated du…
LinusBorg Oct 22, 2022
b0b74a1
fix(runtime-core): custom-element: ensure number casting of camelCase…
LinusBorg Oct 22, 2022
cbc3e67
types(shared): Improve LooseRequired<T> (#6244)
browsnet Oct 26, 2022
8e792d9
types(h): Support passing `props` to `Component` when using `h` (#3219)
pikax Oct 26, 2022
d9de6ca
refactor: move toNumber call out of loop
yyx990803 Oct 26, 2022
de60f54
fix(ssr): v-slot stop empty attribute producing syntax error
tjk Mar 1, 2021
b190cbc
different strategy but changing api, might be no go
tjk Mar 1, 2021
1cf371a
bit cleaner
tjk Mar 1, 2021
1c2ec9f
change test to just check the syntax error is not emitted
tjk Mar 10, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions .eslintrc.js
Expand Up @@ -69,6 +69,14 @@ module.exports = {
'no-restricted-globals': ['error', ...NodeGlobals],
'no-restricted-syntax': 'off'
}
},
// Node scripts
{
files: ['scripts/**', './*.js', 'packages/**/index.js', 'packages/size-check/**'],
rules: {
'no-restricted-globals': 'off',
'no-restricted-syntax': 'off'
}
}
]
}
14 changes: 14 additions & 0 deletions .github/contributing.md
Expand Up @@ -40,6 +40,20 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before

- No need to worry about code style as long as you have installed the dev dependencies - modified files are automatically formatted with Prettier on commit (by invoking [Git Hooks](https://git-scm.com/docs/githooks) via [yorkie](https://github.com/yyx990803/yorkie)).

### Advanced Pull Request Tips

- The PR should fix the intended bug **only** and not introduce unrelated changes. This includes unnecessary refactors - a PR should focus on the fix and not code style, this makes it easier to trace changes in the future.

- Consider the performance / size impact of the changes, and whether the bug being fixes justifies the cost. If the bug being fixed is a very niche edge case, we should try to minimize the size / perf cost to make it worthwhile.

- Is the code perf-sensitive (e.g. in "hot paths" like component updates or the vdom patch function?)
- If the branch is dev-only, performance is less of a concern.

- Check how much extra bundle size the change introduces.
- Make sure to put dev-only code in `__DEV__` branches so they are tree-shakable.
- Runtime code is more sensitive to size increase than compiler code.
- Make sure it doesn't accidentally cause dev-only or compiler-only code branches to be included in the runtime build. Notable case is that some functions in `@vue/shared` are compiler-only and should not be used in runtime code, e.g. `isHTMLTag` and `isSVGTag`.

## Development Setup

You will need [Node.js](https://nodejs.org) **version 16+**, and [PNPM](https://pnpm.io) **version 7+**.
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -6,6 +6,10 @@ on:
pull_request:
branches:
- main

permissions:
contents: read # to fetch code (actions/checkout)

jobs:
unit-test:
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release-tag.yml
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -7,3 +7,4 @@ explorations
TODOs.md
*.log
.idea
.eslintcache
36 changes: 36 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,39 @@
## [3.2.41](https://github.com/vuejs/core/compare/v3.2.40...v3.2.41) (2022-10-14)


### Bug Fixes

* **devtools:** avoid memory leak caused by devtools event buffer ([24f4c47](https://github.com/vuejs/core/commit/24f4c479d661698afd967cf428f9439be4578a04)), closes [#6591](https://github.com/vuejs/core/issues/6591)
* **devtools:** use cleanupBuffer instead of modifying _buffer ([#6812](https://github.com/vuejs/core/issues/6812)) ([35a113e](https://github.com/vuejs/core/commit/35a113eda43a49e921a6eb60d45db81dc847d665))
* **effectScope:** calling off() of a detached scope should not break currentScope ([a71f9ac](https://github.com/vuejs/core/commit/a71f9ac41af464fdb69220e69c50739dd3a8f365))
* **runtime-core:** ensure that errors in slot function execution do not affect block tracking ([#5670](https://github.com/vuejs/core/issues/5670)) ([82a73da](https://github.com/vuejs/core/commit/82a73da351bb5d26735f734ae2540a3033c00c9e)), closes [#5657](https://github.com/vuejs/core/issues/5657)
* **runtime-core:** fix v-for ref reactivity behavior difference between prod and dev ([#6714](https://github.com/vuejs/core/issues/6714)) ([9ae796d](https://github.com/vuejs/core/commit/9ae796d1567f1b0acb08659a2363a54b525a9ee4)), closes [#6697](https://github.com/vuejs/core/issues/6697)
* **runtime-dom:** fix event timestamp check in iframes ([5ee4053](https://github.com/vuejs/core/commit/5ee40532a63e0b792e0c1eccf3cf68546a4e23e9)), closes [#2513](https://github.com/vuejs/core/issues/2513) [#3933](https://github.com/vuejs/core/issues/3933) [#5474](https://github.com/vuejs/core/issues/5474)



## [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)


Expand Down
8 changes: 4 additions & 4 deletions package.json
@@ -1,15 +1,15 @@
{
"private": true,
"version": "3.2.39",
"version": "3.2.41",
"packageManager": "pnpm@7.1.0",
"scripts": {
"dev": "node scripts/dev.js",
"build": "node scripts/build.js",
"size": "run-s size-global size-baseline",
"size-global": "node scripts/build.js vue runtime-dom -f global -p",
"size-baseline": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler && cd packages/size-check && vite build && node brotli",
"lint": "eslint --ext .ts packages/*/{src,__tests__}/**.ts",
"format": "prettier --write --parser typescript \"packages/**/*.ts?(x)\"",
"lint": "eslint --cache --ext .ts packages/*/{src,__tests__}/**.ts",
"format": "prettier --write --cache --parser typescript \"packages/**/*.ts?(x)\"",
"test": "run-s \"test-unit {@}\" \"test-e2e {@}\"",
"test-unit": "jest --filter ./scripts/filter-unit.js",
"test-e2e": "node scripts/build.js vue -f global -d && jest --filter ./scripts/filter-e2e.js --runInBand",
Expand Down Expand Up @@ -80,7 +80,7 @@
"marked": "^4.0.10",
"minimist": "^1.2.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.3.1",
"prettier": "^2.7.1",
"puppeteer": "^10.0.0",
"rollup": "~2.38.5",
"rollup-plugin-node-builtins": "^2.1.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-core",
"version": "3.2.39",
"version": "3.2.41",
"description": "@vue/compiler-core",
"main": "index.js",
"module": "dist/compiler-core.esm-bundler.js",
Expand Down Expand Up @@ -32,7 +32,7 @@
},
"homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-core#readme",
"dependencies": {
"@vue/shared": "3.2.39",
"@vue/shared": "3.2.41",
"@babel/parser": "^7.16.4",
"estree-walker": "^2.0.2",
"source-map": "^0.6.1"
Expand Down
3 changes: 2 additions & 1 deletion packages/compiler-core/src/index.ts
Expand Up @@ -43,7 +43,8 @@ export { processIf } from './transforms/vIf'
export { processFor, createForLoopParams } from './transforms/vFor'
export {
transformExpression,
processExpression
processExpression,
stringifyExpression
} from './transforms/transformExpression'
export {
buildSlots,
Expand Down
61 changes: 34 additions & 27 deletions packages/compiler-core/src/parse.ts
Expand Up @@ -257,34 +257,41 @@ function parseChildren(
const shouldCondense = context.options.whitespace !== 'preserve'
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i]
if (!context.inPre && node.type === NodeTypes.TEXT) {
if (!/[^\t\r\n\f ]/.test(node.content)) {
const prev = nodes[i - 1]
const next = nodes[i + 1]
// Remove if:
// - the whitespace is the first or last node, or:
// - (condense mode) the whitespace is adjacent to a comment, or:
// - (condense mode) the whitespace is between two elements AND contains newline
if (
!prev ||
!next ||
(shouldCondense &&
(prev.type === NodeTypes.COMMENT ||
next.type === NodeTypes.COMMENT ||
(prev.type === NodeTypes.ELEMENT &&
next.type === NodeTypes.ELEMENT &&
/[\r\n]/.test(node.content))))
) {
removedWhitespace = true
nodes[i] = null as any
} else {
// Otherwise, the whitespace is condensed into a single space
node.content = ' '
if (node.type === NodeTypes.TEXT) {
if (!context.inPre) {
if (!/[^\t\r\n\f ]/.test(node.content)) {
const prev = nodes[i - 1]
const next = nodes[i + 1]
// Remove if:
// - the whitespace is the first or last node, or:
// - (condense mode) the whitespace is adjacent to a comment, or:
// - (condense mode) the whitespace is between two elements AND contains newline
if (
!prev ||
!next ||
(shouldCondense &&
(prev.type === NodeTypes.COMMENT ||
next.type === NodeTypes.COMMENT ||
(prev.type === NodeTypes.ELEMENT &&
next.type === NodeTypes.ELEMENT &&
/[\r\n]/.test(node.content))))
) {
removedWhitespace = true
nodes[i] = null as any
} else {
// Otherwise, the whitespace is condensed into a single space
node.content = ' '
}
} else if (shouldCondense) {
// in condense mode, consecutive whitespaces in text are condensed
// down to a single space.
node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ')
}
} else if (shouldCondense) {
// in condense mode, consecutive whitespaces in text are condensed
// down to a single space.
node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ')
} else {
// #6410 normalize windows newlines in <pre>:
// 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.
Expand Down
5 changes: 2 additions & 3 deletions packages/compiler-core/src/runtimeHelpers.ts
Expand Up @@ -42,8 +42,7 @@ export const IS_MEMO_SAME = Symbol(__DEV__ ? `isMemoSame` : ``)

// Name mapping for runtime helpers that need to be imported from 'vue' in
// generated code. Make sure these are correctly exported in the runtime!
// Using `any` here because TS doesn't allow symbols as index type.
export const helperNameMap: any = {
export const helperNameMap: Record<symbol, string> = {
[FRAGMENT]: `Fragment`,
[TELEPORT]: `Teleport`,
[SUSPENSE]: `Suspense`,
Expand Down Expand Up @@ -85,7 +84,7 @@ export const helperNameMap: any = {
[IS_MEMO_SAME]: `isMemoSame`
}

export function registerRuntimeHelpers(helpers: any) {
export function registerRuntimeHelpers(helpers: Record<symbol, string>) {
Object.getOwnPropertySymbols(helpers).forEach(s => {
helperNameMap[s] = helpers[s]
})
Expand Down
33 changes: 20 additions & 13 deletions packages/compiler-core/src/transforms/transformElement.ts
Expand Up @@ -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
Expand Down Expand Up @@ -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__) {
Expand Down Expand Up @@ -643,7 +649,7 @@ 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),
Expand All @@ -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)) {
Expand All @@ -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),
Expand Down
Expand Up @@ -361,7 +361,7 @@ function canPrefix(id: Identifier) {
return true
}

function stringifyExpression(exp: ExpressionNode | string): string {
export function stringifyExpression(exp: ExpressionNode | string): string {
if (isString(exp)) {
return exp
} else if (exp.type === NodeTypes.SIMPLE_EXPRESSION) {
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-core/src/transforms/vOn.ts
Expand Up @@ -54,9 +54,9 @@ export const transformOn: DirectiveTransform = (
? // 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
: // preserve case for plain element listeners that have uppercase
// letters, as these may be custom elements' custom events
: `on:${rawName}`
`on:${rawName}`
eventName = createSimpleExpression(eventString, true, arg.loc)
} else {
// #2388
Expand Down
6 changes: 3 additions & 3 deletions packages/compiler-dom/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-dom",
"version": "3.2.39",
"version": "3.2.41",
"description": "@vue/compiler-dom",
"main": "index.js",
"module": "dist/compiler-dom.esm-bundler.js",
Expand Down Expand Up @@ -37,7 +37,7 @@
},
"homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-dom#readme",
"dependencies": {
"@vue/shared": "3.2.39",
"@vue/compiler-core": "3.2.39"
"@vue/shared": "3.2.41",
"@vue/compiler-core": "3.2.41"
}
}
@@ -1,5 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`dynamic v-on + static v-on should merged 1`] = `
"import { toHandlerKey as _toHandlerKey, mergeProps as _mergeProps, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"

export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock(\\"input\\", _mergeProps({
onBlur: _cache[0] || (_cache[0] = (...args) => (_ctx.onBlur && _ctx.onBlur(...args)))
}, {
[_toHandlerKey(_ctx.validateEvent)]: _cache[1] || (_cache[1] = (...args) => (_ctx.onValidateEvent && _ctx.onValidateEvent(...args)))
}), null, 16 /* FULL_PROPS */))
}"
`;

exports[`should not hoist srcset URLs in SSR mode 1`] = `
"import { resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode } from \\"vue\\"
import { ssrRenderAttr as _ssrRenderAttr, ssrRenderComponent as _ssrRenderComponent } from \\"vue/server-renderer\\"
Expand Down
9 changes: 9 additions & 0 deletions packages/compiler-sfc/__tests__/compileTemplate.spec.ts
Expand Up @@ -174,3 +174,12 @@ test('should not hoist srcset URLs in SSR mode', () => {
})
expect(code).toMatchSnapshot()
})

// #6742
test('dynamic v-on + static v-on should merged', () => {
const source = `<input @blur="onBlur" @[validateEvent]="onValidateEvent">`

const result = compile({ filename: 'example.vue', source })

expect(result.code).toMatchSnapshot()
})