Skip to content

Commit 43e4164

Browse files
authored
Merge branch 'main' into edison/fix/12453
2 parents c1e6e85 + 35aeae7 commit 43e4164

34 files changed

+750
-37
lines changed

CHANGELOG.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,41 @@
1+
## [3.5.14](https://github.com/vuejs/core/compare/v3.5.13...v3.5.14) (2025-05-15)
2+
3+
4+
### Bug Fixes
5+
6+
* **compat:** correct deprecation message for v-bind.sync usage ([#13137](https://github.com/vuejs/core/issues/13137)) ([466b30f](https://github.com/vuejs/core/commit/466b30f4049ec89fb282624ec17d1a93472ab93f)), closes [#13133](https://github.com/vuejs/core/issues/13133)
7+
* **compiler-core:** remove slot cache from parent renderCache during unmounting ([#13215](https://github.com/vuejs/core/issues/13215)) ([5d166f3](https://github.com/vuejs/core/commit/5d166f3796a03a497435fc079c6a83a4e9c6cf52))
8+
* **compiler-sfc:** fix scope handling for props destructure in function parameters and catch clauses ([8e34357](https://github.com/vuejs/core/commit/8e3435779a667de485cf9efd78667d0ca14c5f84)), closes [#12790](https://github.com/vuejs/core/issues/12790)
9+
* **compiler-sfc:** treat the return value of `useTemplateRef` as a definite ref ([#13197](https://github.com/vuejs/core/issues/13197)) ([8ae1122](https://github.com/vuejs/core/commit/8ae11226e8ee938615e17c7b81dc38ae3f7cefb9))
10+
* **compiler:** fix spelling error in domTagConfig ([#13043](https://github.com/vuejs/core/issues/13043)) ([388295b](https://github.com/vuejs/core/commit/388295b27f3cc69eba25d325bbe60a36a3df831a))
11+
* **customFormatter:** properly accessing ref value during debugger ([#12948](https://github.com/vuejs/core/issues/12948)) ([fdbd026](https://github.com/vuejs/core/commit/fdbd02658301dd794fe0c84f0018d080a07fca9f))
12+
* **hmr/teleport:** adjust static children traversal for HMR in dev mode ([#12819](https://github.com/vuejs/core/issues/12819)) ([5e37dd0](https://github.com/vuejs/core/commit/5e37dd009562bcd8080a200c32abde2d6e4f0305)), closes [#12816](https://github.com/vuejs/core/issues/12816)
13+
* **hmr:** avoid hydration for hmr root reload ([#12450](https://github.com/vuejs/core/issues/12450)) ([1f98a9c](https://github.com/vuejs/core/commit/1f98a9c493d01c21befa90107f0593bc92a58932)), closes [vitejs/vite-plugin-vue#146](https://github.com/vitejs/vite-plugin-vue/issues/146) [vitejs/vite-plugin-vue#477](https://github.com/vitejs/vite-plugin-vue/issues/477)
14+
* **hmr:** avoid hydration for hmr updating ([#12262](https://github.com/vuejs/core/issues/12262)) ([9c4dbbc](https://github.com/vuejs/core/commit/9c4dbbc5185125835ad3e49baba303bd54676111)), closes [#7706](https://github.com/vuejs/core/issues/7706) [#8170](https://github.com/vuejs/core/issues/8170)
15+
* **reactivity:** ensure markRaw objects are not reactive ([#12824](https://github.com/vuejs/core/issues/12824)) ([295b5ec](https://github.com/vuejs/core/commit/295b5ec19b6a52c4a56652cc4d6e93a4ea7c14ed)), closes [#12807](https://github.com/vuejs/core/issues/12807)
16+
* **reactivity:** ensure multiple effectScope on() and off() calls maintains correct active scope ([22dcbf3](https://github.com/vuejs/core/commit/22dcbf3e20eb84f69c8952f6f70d9990136a4a68)), closes [#12631](https://github.com/vuejs/core/issues/12631) [#12632](https://github.com/vuejs/core/issues/12632) [#12641](https://github.com/vuejs/core/issues/12641)
17+
* **reactivity:** should not recompute if computed does not track reactive data ([#12341](https://github.com/vuejs/core/issues/12341)) ([0b23fd2](https://github.com/vuejs/core/commit/0b23fd23833cf085e7e112bf4435cfc9b360d072)), closes [#12337](https://github.com/vuejs/core/issues/12337)
18+
* **runtime-core:** stop tracking deps in setRef during unmount ([#13210](https://github.com/vuejs/core/issues/13210)) ([016c472](https://github.com/vuejs/core/commit/016c472bd2e7604b21c69dee1da8545ce26e4d2f))
19+
* **runtime-core:** update __vnode of static nodes when patching along the optimized path ([#13223](https://github.com/vuejs/core/issues/13223)) ([b3ecee3](https://github.com/vuejs/core/commit/b3ecee3da8ed5c55dea89ce6b4b376b2b722b018))
20+
* **runtime-core:** inherit comment nodes during block patch in production build ([#10748](https://github.com/vuejs/core/issues/10748)) ([6264505](https://github.com/vuejs/core/commit/626450590d81f79117b34d2a73073b1dc8f551bd)), closes [#10747](https://github.com/vuejs/core/issues/10747) [#12650](https://github.com/vuejs/core/issues/12650)
21+
* **runtime-core:** prevent unmounted vnode from being inserted during transition leave ([#12862](https://github.com/vuejs/core/issues/12862)) ([d6a6ec1](https://github.com/vuejs/core/commit/d6a6ec13ce521683bfb2a22932778ef7b51f8600)), closes [#12860](https://github.com/vuejs/core/issues/12860)
22+
* **runtime-core:** respect immutability for readonly reactive arrays in `v-for` ([#13091](https://github.com/vuejs/core/issues/13091)) ([3f27c58](https://github.com/vuejs/core/commit/3f27c58ffbd4309df369bc89493fdc284dc540bb)), closes [#13087](https://github.com/vuejs/core/issues/13087)
23+
* **runtime-dom:** always treat autocorrect as attribute ([#13001](https://github.com/vuejs/core/issues/13001)) ([1499135](https://github.com/vuejs/core/commit/1499135c227236e037bb746beeb777941b0b58ff)), closes [#5705](https://github.com/vuejs/core/issues/5705)
24+
* **slots:** properly warn if slot invoked in setup ([#12195](https://github.com/vuejs/core/issues/12195)) ([9196222](https://github.com/vuejs/core/commit/9196222ae1d63b52b35ac5fbf5e71494587ccf05)), closes [#12194](https://github.com/vuejs/core/issues/12194)
25+
* **ssr:** properly init slots during ssr rendering ([#12441](https://github.com/vuejs/core/issues/12441)) ([2206cd2](https://github.com/vuejs/core/commit/2206cd235a1627c540e795e378b7564a55b47313)), closes [#12438](https://github.com/vuejs/core/issues/12438)
26+
* **transition:** fix KeepAlive with transition out-in mode behavior in production ([#12468](https://github.com/vuejs/core/issues/12468)) ([343c891](https://github.com/vuejs/core/commit/343c89122448719bd6ed6bd9de986dfb2721d6bf)), closes [#12465](https://github.com/vuejs/core/issues/12465)
27+
* **TransitionGroup:** reset prevChildren to prevent memory leak ([#13183](https://github.com/vuejs/core/issues/13183)) ([8b848cb](https://github.com/vuejs/core/commit/8b848cbbd2af337d23e19e202f9ab433f8580855)), closes [#13181](https://github.com/vuejs/core/issues/13181)
28+
* **types:** allow return any for Options API lifecycle hooks ([#5914](https://github.com/vuejs/core/issues/5914)) ([06310e8](https://github.com/vuejs/core/commit/06310e82f5bed62d1b9733dcb18cd8d6edc988de))
29+
* **types:** the directive's modifiers should be optional ([#12605](https://github.com/vuejs/core/issues/12605)) ([10e54dc](https://github.com/vuejs/core/commit/10e54dcc86a7967f3196d96200bcbd1d3d42082f))
30+
* **typos:** fix comments referencing transformElement.ts ([#12551](https://github.com/vuejs/core/issues/12551))[ci-skip] ([11c053a](https://github.com/vuejs/core/commit/11c053a5429ad0d27a0e2c78b6b026ea00ace116))
31+
32+
33+
### Features
34+
35+
* **types:** add type TemplateRef ([#12645](https://github.com/vuejs/core/issues/12645)) ([636a861](https://github.com/vuejs/core/commit/636a8619f06c71dfd79f7f6412fd130c4f84226f))
36+
37+
38+
139
## [3.5.13](https://github.com/vuejs/core/compare/v3.5.12...v3.5.13) (2024-11-15)
240

341

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"private": true,
3-
"version": "3.5.13",
3+
"version": "3.5.14",
44
"packageManager": "[email protected]",
55
"type": "module",
66
"scripts": {

packages/compiler-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/compiler-core",
3-
"version": "3.5.13",
3+
"version": "3.5.14",
44
"description": "@vue/compiler-core",
55
"main": "index.js",
66
"module": "dist/compiler-core.esm-bundler.js",

packages/compiler-core/src/codegen.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,9 @@ function createCodegenContext(
188188
name = content
189189
}
190190
}
191-
addMapping(node.loc.start, name)
191+
if (node.loc.source) {
192+
addMapping(node.loc.start, name)
193+
}
192194
}
193195
if (newlineIndex === NewlineType.Unknown) {
194196
// multiple newlines, full iteration
@@ -225,7 +227,7 @@ function createCodegenContext(
225227
context.column = code.length - newlineIndex
226228
}
227229
}
228-
if (node && node.loc !== locStub) {
230+
if (node && node.loc !== locStub && node.loc.source) {
229231
addMapping(node.loc.end)
230232
}
231233
}

packages/compiler-dom/__tests__/transforms/validateHtmlNesting.spec.ts

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type CompilerError, compile } from '../../src'
2+
import { isValidHTMLNesting } from '../../src/htmlNesting'
23

34
describe('validate html nesting', () => {
45
it('should warn with p > div', () => {
@@ -17,4 +18,185 @@ describe('validate html nesting', () => {
1718
})
1819
expect(err).toBeUndefined()
1920
})
21+
22+
// #13318
23+
it('should not warn when parent tag is template', () => {
24+
let err: CompilerError | undefined
25+
compile(`<template><tr/></template>`, {
26+
onWarn: e => (err = e),
27+
})
28+
expect(err).toBeUndefined()
29+
})
30+
})
31+
32+
/**
33+
* Copied from https://github.com/MananTank/validate-html-nesting
34+
* with ISC license
35+
*/
36+
describe('isValidHTMLNesting', () => {
37+
test('form', () => {
38+
// invalid
39+
expect(isValidHTMLNesting('form', 'form')).toBe(false)
40+
41+
// valid
42+
expect(isValidHTMLNesting('form', 'div')).toBe(true)
43+
expect(isValidHTMLNesting('form', 'input')).toBe(true)
44+
expect(isValidHTMLNesting('form', 'select')).toBe(true)
45+
expect(isValidHTMLNesting('form', 'button')).toBe(true)
46+
expect(isValidHTMLNesting('form', 'label')).toBe(true)
47+
expect(isValidHTMLNesting('form', 'h1')).toBe(true)
48+
})
49+
50+
test('p', () => {
51+
// invalid
52+
expect(isValidHTMLNesting('p', 'p')).toBe(false)
53+
expect(isValidHTMLNesting('p', 'div')).toBe(false)
54+
expect(isValidHTMLNesting('p', 'hr')).toBe(false)
55+
expect(isValidHTMLNesting('p', 'blockquote')).toBe(false)
56+
expect(isValidHTMLNesting('p', 'pre')).toBe(false)
57+
58+
// valid
59+
expect(isValidHTMLNesting('p', 'a')).toBe(true)
60+
expect(isValidHTMLNesting('p', 'span')).toBe(true)
61+
expect(isValidHTMLNesting('p', 'abbr')).toBe(true)
62+
expect(isValidHTMLNesting('p', 'button')).toBe(true)
63+
expect(isValidHTMLNesting('p', 'b')).toBe(true)
64+
expect(isValidHTMLNesting('p', 'i')).toBe(true)
65+
expect(isValidHTMLNesting('p', 'input')).toBe(true)
66+
expect(isValidHTMLNesting('p', 'label')).toBe(true)
67+
})
68+
69+
test('a', () => {
70+
// invalid
71+
expect(isValidHTMLNesting('a', 'a')).toBe(false)
72+
73+
// valid
74+
expect(isValidHTMLNesting('a', 'div')).toBe(true)
75+
expect(isValidHTMLNesting('a', 'span')).toBe(true)
76+
})
77+
78+
test('button', () => {
79+
// invalid
80+
expect(isValidHTMLNesting('button', 'button')).toBe(false)
81+
82+
// valid
83+
expect(isValidHTMLNesting('button', 'div')).toBe(true)
84+
expect(isValidHTMLNesting('button', 'span')).toBe(true)
85+
})
86+
87+
test('table', () => {
88+
// invalid
89+
expect(isValidHTMLNesting('table', 'tr')).toBe(false)
90+
expect(isValidHTMLNesting('table', 'table')).toBe(false)
91+
expect(isValidHTMLNesting('table', 'td')).toBe(false)
92+
93+
// valid
94+
expect(isValidHTMLNesting('table', 'thead')).toBe(true)
95+
expect(isValidHTMLNesting('table', 'tbody')).toBe(true)
96+
expect(isValidHTMLNesting('table', 'tfoot')).toBe(true)
97+
expect(isValidHTMLNesting('table', 'caption')).toBe(true)
98+
expect(isValidHTMLNesting('table', 'colgroup')).toBe(true)
99+
})
100+
101+
test('td', () => {
102+
// valid
103+
expect(isValidHTMLNesting('td', 'span')).toBe(true)
104+
expect(isValidHTMLNesting('tr', 'td')).toBe(true)
105+
106+
// invalid
107+
expect(isValidHTMLNesting('td', 'td')).toBe(false)
108+
expect(isValidHTMLNesting('div', 'td')).toBe(false)
109+
})
110+
111+
test('tbody', () => {
112+
// invalid
113+
expect(isValidHTMLNesting('tbody', 'td')).toBe(false)
114+
115+
// valid
116+
expect(isValidHTMLNesting('tbody', 'tr')).toBe(true)
117+
})
118+
119+
test('tr', () => {
120+
// invalid
121+
expect(isValidHTMLNesting('tr', 'tr')).toBe(false)
122+
expect(isValidHTMLNesting('table', 'tr')).toBe(false)
123+
124+
// valid
125+
expect(isValidHTMLNesting('tbody', 'tr')).toBe(true)
126+
expect(isValidHTMLNesting('thead', 'tr')).toBe(true)
127+
expect(isValidHTMLNesting('tfoot', 'tr')).toBe(true)
128+
expect(isValidHTMLNesting('tr', 'td')).toBe(true)
129+
expect(isValidHTMLNesting('tr', 'th')).toBe(true)
130+
})
131+
132+
test('li', () => {
133+
// invalid
134+
expect(isValidHTMLNesting('li', 'li')).toBe(false)
135+
// valid
136+
expect(isValidHTMLNesting('li', 'div')).toBe(true)
137+
expect(isValidHTMLNesting('li', 'ul')).toBe(true)
138+
})
139+
140+
test('headings', () => {
141+
// invalid
142+
expect(isValidHTMLNesting('h1', 'h1')).toBe(false)
143+
expect(isValidHTMLNesting('h2', 'h1')).toBe(false)
144+
expect(isValidHTMLNesting('h3', 'h1')).toBe(false)
145+
expect(isValidHTMLNesting('h1', 'h6')).toBe(false)
146+
147+
// valid
148+
expect(isValidHTMLNesting('h1', 'div')).toBe(true)
149+
})
150+
151+
describe('SVG', () => {
152+
test('svg', () => {
153+
// invalid non-svg tags as children
154+
expect(isValidHTMLNesting('svg', 'div')).toBe(false)
155+
expect(isValidHTMLNesting('svg', 'img')).toBe(false)
156+
expect(isValidHTMLNesting('svg', 'p')).toBe(false)
157+
expect(isValidHTMLNesting('svg', 'h2')).toBe(false)
158+
expect(isValidHTMLNesting('svg', 'span')).toBe(false)
159+
160+
// valid non-svg tags as children
161+
expect(isValidHTMLNesting('svg', 'a')).toBe(true)
162+
expect(isValidHTMLNesting('svg', 'textarea')).toBe(true)
163+
expect(isValidHTMLNesting('svg', 'input')).toBe(true)
164+
expect(isValidHTMLNesting('svg', 'select')).toBe(true)
165+
166+
// valid svg tags as children
167+
expect(isValidHTMLNesting('svg', 'g')).toBe(true)
168+
expect(isValidHTMLNesting('svg', 'ellipse')).toBe(true)
169+
expect(isValidHTMLNesting('svg', 'feOffset')).toBe(true)
170+
})
171+
172+
test('foreignObject', () => {
173+
// valid
174+
expect(isValidHTMLNesting('foreignObject', 'g')).toBe(true)
175+
expect(isValidHTMLNesting('foreignObject', 'div')).toBe(true)
176+
expect(isValidHTMLNesting('foreignObject', 'a')).toBe(true)
177+
expect(isValidHTMLNesting('foreignObject', 'textarea')).toBe(true)
178+
})
179+
180+
test('g', () => {
181+
// valid
182+
expect(isValidHTMLNesting('g', 'div')).toBe(true)
183+
expect(isValidHTMLNesting('g', 'p')).toBe(true)
184+
expect(isValidHTMLNesting('g', 'a')).toBe(true)
185+
expect(isValidHTMLNesting('g', 'textarea')).toBe(true)
186+
expect(isValidHTMLNesting('g', 'g')).toBe(true)
187+
})
188+
189+
test('dl', () => {
190+
// valid
191+
expect(isValidHTMLNesting('dl', 'dt')).toBe(true)
192+
expect(isValidHTMLNesting('dl', 'dd')).toBe(true)
193+
expect(isValidHTMLNesting('dl', 'div')).toBe(true)
194+
expect(isValidHTMLNesting('div', 'dt')).toBe(true)
195+
expect(isValidHTMLNesting('div', 'dd')).toBe(true)
196+
197+
// invalid
198+
expect(isValidHTMLNesting('span', 'dt')).toBe(false)
199+
expect(isValidHTMLNesting('span', 'dd')).toBe(false)
200+
})
201+
})
20202
})

packages/compiler-dom/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/compiler-dom",
3-
"version": "3.5.13",
3+
"version": "3.5.14",
44
"description": "@vue/compiler-dom",
55
"main": "index.js",
66
"module": "dist/compiler-dom.esm-bundler.js",

packages/compiler-dom/src/htmlNesting.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
* returns true if given parent-child nesting is valid HTML
1212
*/
1313
export function isValidHTMLNesting(parent: string, child: string): boolean {
14+
// if the parent is a template, it can have any child
15+
if (parent === 'template') {
16+
return true
17+
}
18+
1419
// if we know the list of children that are the only valid children for the given parent
1520
if (parent in onlyValidChildren) {
1621
return onlyValidChildren[parent].has(child)

packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineProps.spec.ts.snap

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,27 @@ export default /*@__PURE__*/_defineComponent({
148148
149149
150150
151+
return { }
152+
}
153+
154+
})"
155+
`;
156+
157+
exports[`defineProps > w/ TSTypeAliasDeclaration 1`] = `
158+
"import { defineComponent as _defineComponent } from 'vue'
159+
type FunFoo<O> = (item: O) => boolean;
160+
type FunBar = FunFoo<number>;
161+
162+
export default /*@__PURE__*/_defineComponent({
163+
props: {
164+
foo: { type: Function, required: false, default: () => true },
165+
bar: { type: Function, required: false, default: () => true }
166+
},
167+
setup(__props: any, { expose: __expose }) {
168+
__expose();
169+
170+
171+
151172
return { }
152173
}
153174

packages/compiler-sfc/__tests__/compileScript/defineProps.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,4 +808,30 @@ const props = defineProps({ foo: String })
808808
expect(content).toMatch(`foo: { default: 5.5, type: Number }`)
809809
assertCode(content)
810810
})
811+
812+
test('w/ TSTypeAliasDeclaration', () => {
813+
const { content } = compile(`
814+
<script setup lang="ts">
815+
type FunFoo<O> = (item: O) => boolean;
816+
type FunBar = FunFoo<number>;
817+
withDefaults(
818+
defineProps<{
819+
foo?: FunFoo<number>;
820+
bar?: FunBar;
821+
}>(),
822+
{
823+
foo: () => true,
824+
bar: () => true,
825+
},
826+
);
827+
</script>
828+
`)
829+
assertCode(content)
830+
expect(content).toMatch(
831+
`foo: { type: Function, required: false, default: () => true }`,
832+
)
833+
expect(content).toMatch(
834+
`bar: { type: Function, required: false, default: () => true }`,
835+
)
836+
})
811837
})

packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,29 @@ describe('resolveType', () => {
14341434
colsLg: ['Number'],
14351435
})
14361436
})
1437+
1438+
test('allowArbitraryExtensions', () => {
1439+
const files = {
1440+
'/foo.d.vue.ts': 'export type Foo = number;',
1441+
'/foo.vue': '<template><div /></template>',
1442+
'/bar.d.css.ts': 'export type Bar = string;',
1443+
'/bar.css': ':root { --color: red; }',
1444+
}
1445+
1446+
const { props } = resolve(
1447+
`
1448+
import { Foo } from './foo.vue'
1449+
import { Bar } from './bar.css'
1450+
defineProps<{ foo: Foo; bar: Bar }>()
1451+
`,
1452+
files,
1453+
)
1454+
1455+
expect(props).toStrictEqual({
1456+
foo: ['Number'],
1457+
bar: ['String'],
1458+
})
1459+
})
14371460
})
14381461
})
14391462

0 commit comments

Comments
 (0)