chore: Merge branch 'minor' into vapor

This commit is contained in:
daiwei 2025-06-18 09:30:17 +08:00
commit a0c42ffbbc
39 changed files with 788 additions and 181 deletions

View File

@ -1,3 +1,41 @@
## [3.5.14](https://github.com/vuejs/core/compare/v3.5.13...v3.5.14) (2025-05-15)
### Bug Fixes
* **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)
* **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))
* **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)
* **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))
* **compiler:** fix spelling error in domTagConfig ([#13043](https://github.com/vuejs/core/issues/13043)) ([388295b](https://github.com/vuejs/core/commit/388295b27f3cc69eba25d325bbe60a36a3df831a))
* **customFormatter:** properly accessing ref value during debugger ([#12948](https://github.com/vuejs/core/issues/12948)) ([fdbd026](https://github.com/vuejs/core/commit/fdbd02658301dd794fe0c84f0018d080a07fca9f))
* **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)
* **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)
* **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)
* **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)
* **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)
* **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)
* **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))
* **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))
* **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)
* **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)
* **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)
* **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)
* **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)
* **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)
* **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)
* **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)
* **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))
* **types:** the directive's modifiers should be optional ([#12605](https://github.com/vuejs/core/issues/12605)) ([10e54dc](https://github.com/vuejs/core/commit/10e54dcc86a7967f3196d96200bcbd1d3d42082f))
* **typos:** fix comments referencing transformElement.ts ([#12551](https://github.com/vuejs/core/issues/12551))[ci-skip] ([11c053a](https://github.com/vuejs/core/commit/11c053a5429ad0d27a0e2c78b6b026ea00ace116))
### Features
* **types:** add type TemplateRef ([#12645](https://github.com/vuejs/core/issues/12645)) ([636a861](https://github.com/vuejs/core/commit/636a8619f06c71dfd79f7f6412fd130c4f84226f))
## [3.5.13](https://github.com/vuejs/core/compare/v3.5.12...v3.5.13) (2024-11-15)
@ -8,7 +46,7 @@
* **custom-element:** avoid triggering mutationObserver when relecting props ([352bc88](https://github.com/vuejs/core/commit/352bc88c1bd2fda09c61ab17ea1a5967ffcd7bc0)), closes [#12214](https://github.com/vuejs/core/issues/12214) [#12215](https://github.com/vuejs/core/issues/12215)
* **deps:** update dependency postcss to ^8.4.48 ([#12356](https://github.com/vuejs/core/issues/12356)) ([b5ff930](https://github.com/vuejs/core/commit/b5ff930089985a58c3553977ef999cec2a6708a4))
* **hydration:** the component vnode's el should be updated when a mismatch occurs. ([#12255](https://github.com/vuejs/core/issues/12255)) ([a20a4cb](https://github.com/vuejs/core/commit/a20a4cb36a3e717d1f8f259d0d59f133f508ff0a)), closes [#12253](https://github.com/vuejs/core/issues/12253)
* **reactiivty:** avoid unnecessary watcher effect removal from inactive scope ([2193284](https://github.com/vuejs/core/commit/21932840eae72ffcd357a62ec596aaecc7ec224a)), closes [#5783](https://github.com/vuejs/core/issues/5783) [#5806](https://github.com/vuejs/core/issues/5806)
* **reactivity:** avoid unnecessary watcher effect removal from inactive scope ([2193284](https://github.com/vuejs/core/commit/21932840eae72ffcd357a62ec596aaecc7ec224a)), closes [#5783](https://github.com/vuejs/core/issues/5783) [#5806](https://github.com/vuejs/core/issues/5806)
* **reactivity:** release nested effects/scopes on effect scope stop ([#12373](https://github.com/vuejs/core/issues/12373)) ([bee2f5e](https://github.com/vuejs/core/commit/bee2f5ee62dc0cd04123b737779550726374dd0a)), closes [#12370](https://github.com/vuejs/core/issues/12370)
* **runtime-dom:** set css vars before user onMounted hooks ([2d5c5e2](https://github.com/vuejs/core/commit/2d5c5e25e9b7a56e883674fb434135ac514429b5)), closes [#11533](https://github.com/vuejs/core/issues/11533)
* **runtime-dom:** set css vars on update to handle child forcing reflow in onMount ([#11561](https://github.com/vuejs/core/issues/11561)) ([c4312f9](https://github.com/vuejs/core/commit/c4312f9c715c131a09e552ba46e9beb4b36d55e6))

View File

@ -35,6 +35,7 @@ Please make sure to respect issue requirements and use [the new issue helper](ht
## Stay In Touch
- [X](https://x.com/vuejs)
- [Bluesky](https://bsky.app/profile/vuejs.org)
- [Blog](https://blog.vuejs.org/)
- [Job Board](https://vuejobs.com/?ref=vuejs)

View File

@ -1,7 +1,7 @@
{
"private": true,
"version": "3.5.13",
"packageManager": "pnpm@10.7.0",
"version": "3.5.14",
"packageManager": "pnpm@10.9.0",
"type": "module",
"scripts": {
"dev": "node scripts/dev.js",
@ -69,24 +69,24 @@
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-replace": "5.0.4",
"@swc/core": "^1.11.13",
"@swc/core": "^1.11.24",
"@types/hash-sum": "^1.0.2",
"@types/node": "^22.13.14",
"@types/node": "^22.14.1",
"@types/semver": "^7.7.0",
"@types/serve-handler": "^6.1.4",
"@vitest/ui": "^3.0.2",
"@vitest/coverage-v8": "^3.0.9",
"@vitest/eslint-plugin": "^1.1.38",
"@vitest/coverage-v8": "^3.1.3",
"@vitest/eslint-plugin": "^1.1.44",
"@vue/consolidate": "1.0.0",
"conventional-changelog-cli": "^5.0.0",
"enquirer": "^2.4.1",
"esbuild": "^0.25.2",
"esbuild": "^0.25.4",
"esbuild-plugin-polyfill-node": "^0.3.0",
"eslint": "^9.23.0",
"eslint-plugin-import-x": "^4.9.4",
"eslint": "^9.25.1",
"eslint-plugin-import-x": "^4.11.0",
"estree-walker": "catalog:",
"jsdom": "^26.0.0",
"lint-staged": "^15.5.0",
"jsdom": "^26.1.0",
"lint-staged": "^15.5.1",
"lodash": "^4.17.21",
"magic-string": "^0.30.17",
"markdown-table": "^3.0.4",
@ -96,38 +96,21 @@
"prettier": "^3.5.3",
"pretty-bytes": "^6.1.1",
"pug": "^3.0.3",
"puppeteer": "~24.4.0",
"puppeteer": "~24.8.2",
"rimraf": "^6.0.1",
"rollup": "^4.38.0",
"rollup": "^4.40.2",
"rollup-plugin-dts": "^6.2.1",
"rollup-plugin-esbuild": "^6.2.1",
"rollup-plugin-polyfill-node": "^0.13.0",
"semver": "^7.7.1",
"serve": "^14.2.4",
"serve-handler": "^6.1.6",
"simple-git-hooks": "^2.12.1",
"simple-git-hooks": "^2.13.0",
"todomvc-app-css": "^2.4.3",
"tslib": "^2.8.1",
"typescript": "~5.6.2",
"typescript-eslint": "^8.28.0",
"typescript-eslint": "^8.31.1",
"vite": "catalog:",
"vitest": "^3.0.9"
},
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
"typescript-eslint>eslint": "^9.0.0",
"@typescript-eslint/eslint-plugin>eslint": "^9.0.0",
"@typescript-eslint/parser>eslint": "^9.0.0",
"@typescript-eslint/type-utils>eslint": "^9.0.0",
"@typescript-eslint/utils>eslint": "^9.0.0"
}
},
"onlyBuiltDependencies": [
"@swc/core",
"esbuild",
"puppeteer",
"simple-git-hooks"
]
"vitest": "^3.1.3"
}
}

View File

@ -11,7 +11,7 @@
"vue": "latest"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.3",
"vite": "^6.2.3"
"@vitejs/plugin-vue": "^5.2.4",
"vite": "^6.3.5"
}
}

View File

@ -170,6 +170,11 @@ describe('compiler: cacheStatic transform', () => {
{
/* _ slot flag */
},
{
type: NodeTypes.JS_PROPERTY,
key: { content: '__' },
value: { content: '[0]' },
},
],
})
})
@ -197,6 +202,11 @@ describe('compiler: cacheStatic transform', () => {
{
/* _ slot flag */
},
{
type: NodeTypes.JS_PROPERTY,
key: { content: '__' },
value: { content: '[0]' },
},
],
})
})

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compiler-core",
"version": "3.5.13",
"version": "3.5.14",
"description": "@vue/compiler-core",
"main": "index.js",
"module": "dist/compiler-core.esm-bundler.js",

View File

@ -12,11 +12,14 @@ import {
type RootNode,
type SimpleExpressionNode,
type SlotFunctionExpression,
type SlotsObjectProperty,
type TemplateChildNode,
type TemplateNode,
type TextCallNode,
type VNodeCall,
createArrayExpression,
createObjectProperty,
createSimpleExpression,
getVNodeBlockHelper,
getVNodeHelper,
} from '../ast'
@ -140,6 +143,7 @@ function walk(
}
let cachedAsArray = false
const slotCacheKeys = []
if (toCache.length === children.length && node.type === NodeTypes.ELEMENT) {
if (
node.tagType === ElementTypes.ELEMENT &&
@ -163,6 +167,7 @@ function walk(
// default slot
const slot = getSlotNode(node.codegenNode, 'default')
if (slot) {
slotCacheKeys.push(context.cached.length)
slot.returns = getCacheExpression(
createArrayExpression(slot.returns as TemplateChildNode[]),
)
@ -186,6 +191,7 @@ function walk(
slotName.arg &&
getSlotNode(parent.codegenNode, slotName.arg)
if (slot) {
slotCacheKeys.push(context.cached.length)
slot.returns = getCacheExpression(
createArrayExpression(slot.returns as TemplateChildNode[]),
)
@ -196,10 +202,31 @@ function walk(
if (!cachedAsArray) {
for (const child of toCache) {
slotCacheKeys.push(context.cached.length)
child.codegenNode = context.cache(child.codegenNode!)
}
}
// put the slot cached keys on the slot object, so that the cache
// can be removed when component unmounting to prevent memory leaks
if (
slotCacheKeys.length &&
node.type === NodeTypes.ELEMENT &&
node.tagType === ElementTypes.COMPONENT &&
node.codegenNode &&
node.codegenNode.type === NodeTypes.VNODE_CALL &&
node.codegenNode.children &&
!isArray(node.codegenNode.children) &&
node.codegenNode.children.type === NodeTypes.JS_OBJECT_EXPRESSION
) {
node.codegenNode.children.properties.push(
createObjectProperty(
`__`,
createSimpleExpression(JSON.stringify(slotCacheKeys), false),
) as SlotsObjectProperty,
)
}
function getCacheExpression(value: JSChildNode): CacheExpression {
const exp = context.cache(value)
// #6978, #7138, #7114

View File

@ -342,7 +342,6 @@ export function buildSlots(
: hasForwardedSlots(node.children)
? SlotFlags.FORWARDED
: SlotFlags.STABLE
let slots = createObjectExpression(
slotsProperties.concat(
createObjectProperty(

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compiler-dom",
"version": "3.5.13",
"version": "3.5.14",
"description": "@vue/compiler-dom",
"main": "index.js",
"module": "dist/compiler-dom.esm-bundler.js",

View File

@ -196,6 +196,25 @@ return () => {}
}"
`;
exports[`sfc reactive props destructure > handle function parameters with same name as destructured props 1`] = `
"
export default {
setup(__props) {
function test(value) {
try {
} catch {
}
}
console.log(__props.value)
return () => {}
}
}"
`;
exports[`sfc reactive props destructure > multi-variable declaration 1`] = `
"
export default {

View File

@ -360,6 +360,22 @@ describe('sfc reactive props destructure', () => {
expect(content).toMatch(`props: ['item'],`)
})
test('handle function parameters with same name as destructured props', () => {
const { content } = compile(`
<script setup>
const { value } = defineProps()
function test(value) {
try {
} catch {
}
}
console.log(value)
</script>
`)
assertCode(content)
expect(content).toMatch(`console.log(__props.value)`)
})
test('defineProps/defineEmits in multi-variable declaration (full removal)', () => {
const { content } = compile(`
<script setup>

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compiler-sfc",
"version": "3.5.13",
"version": "3.5.14",
"description": "@vue/compiler-sfc",
"main": "dist/compiler-sfc.cjs.js",
"module": "dist/compiler-sfc.esm-browser.js",
@ -63,6 +63,6 @@
"postcss-modules": "^6.0.1",
"postcss-selector-parser": "^7.1.0",
"pug": "^3.0.3",
"sass": "^1.86.0"
"sass": "^1.86.3"
}
}

View File

@ -1120,6 +1120,7 @@ function walkDeclaration(
m === userImportAliases['shallowRef'] ||
m === userImportAliases['customRef'] ||
m === userImportAliases['toRef'] ||
m === userImportAliases['useTemplateRef'] ||
m === DEFINE_MODEL,
)
) {

View File

@ -291,7 +291,8 @@ export function transformDestructuredProps(
parent && parentStack.pop()
if (
(node.type === 'BlockStatement' && !isFunctionType(parent!)) ||
isFunctionType(node)
isFunctionType(node) ||
node.type === 'CatchClause'
) {
popScope()
}

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compiler-ssr",
"version": "3.5.13",
"version": "3.5.14",
"description": "@vue/compiler-ssr",
"main": "dist/compiler-ssr.cjs.js",
"types": "dist/compiler-ssr.d.ts",

View File

@ -1017,6 +1017,17 @@ describe('reactivity/computed', () => {
expect(cValue.value).toBe(1)
})
test('should not recompute if computed does not track reactive data', async () => {
const spy = vi.fn()
const c1 = computed(() => spy())
c1.value
ref(0).value++ // update globalVersion
c1.value
expect(spy).toBeCalledTimes(1)
})
test('computed should remain live after losing all subscribers', () => {
const state = reactive({ a: 1 })
const p = computed(() => state.a + 1)

View File

@ -1,6 +1,6 @@
{
"name": "@vue/reactivity",
"version": "3.5.13",
"version": "3.5.14",
"description": "@vue/reactivity",
"main": "index.js",
"module": "dist/reactivity.esm-bundler.js",

View File

@ -324,4 +324,98 @@ describe('component: slots', () => {
'Slot "default" invoked outside of the render function',
).not.toHaveBeenWarned()
})
test('basic warn', () => {
const Comp = {
setup(_: any, { slots }: any) {
slots.default && slots.default()
return () => null
},
}
const App = {
setup() {
return () => h(Comp, () => h('div'))
},
}
createApp(App).mount(nodeOps.createElement('div'))
expect(
'Slot "default" invoked outside of the render function',
).toHaveBeenWarned()
})
test('basic warn when mounting another app in setup', () => {
const Comp = {
setup(_: any, { slots }: any) {
slots.default?.()
return () => null
},
}
const mountComp = () => {
createApp({
setup() {
return () => h(Comp, () => 'msg')
},
}).mount(nodeOps.createElement('div'))
}
const App = {
setup() {
mountComp()
return () => null
},
}
createApp(App).mount(nodeOps.createElement('div'))
expect(
'Slot "default" invoked outside of the render function',
).toHaveBeenWarned()
})
test('should not warn when render in setup', () => {
const container = {
setup(_: any, { slots }: any) {
return () => slots.default && slots.default()
},
}
const comp = h(container, null, () => h('div'))
const App = {
setup() {
render(h(comp), nodeOps.createElement('div'))
return () => null
},
}
createApp(App).mount(nodeOps.createElement('div'))
expect(
'Slot "default" invoked outside of the render function',
).not.toHaveBeenWarned()
})
test('basic warn when render in setup', () => {
const container = {
setup(_: any, { slots }: any) {
slots.default && slots.default()
return () => null
},
}
const comp = h(container, null, () => h('div'))
const App = {
setup() {
render(h(comp), nodeOps.createElement('div'))
return () => null
},
}
createApp(App).mount(nodeOps.createElement('div'))
expect(
'Slot "default" invoked outside of the render function',
).toHaveBeenWarned()
})
})

View File

@ -1198,4 +1198,51 @@ describe('BaseTransition', () => {
test('should not error on KeepAlive w/ function children', () => {
expect(() => mount({}, () => () => h('div'), true)).not.toThrow()
})
// #12465
test('mode: "out-in" w/ KeepAlive + fallthrough attrs (prod mode)', async () => {
__DEV__ = false
async function testOutIn({ trueBranch, falseBranch }: ToggleOptions) {
const toggle = ref(true)
const { props, cbs } = mockProps({ mode: 'out-in' }, true)
const root = nodeOps.createElement('div')
const App = {
render() {
return h(
BaseTransition,
{
...props,
class: 'test',
},
() =>
h(KeepAlive, null, toggle.value ? trueBranch() : falseBranch()),
)
},
}
render(h(App), root)
expect(serializeInner(root)).toBe(`<div class="test">0</div>`)
// trigger toggle
toggle.value = false
await nextTick()
expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)
expect(serialize((props.onBeforeLeave as any).mock.calls[0][0])).toBe(
`<div class="test">0</div>`,
)
expect(props.onLeave).toHaveBeenCalledTimes(1)
expect(serialize((props.onLeave as any).mock.calls[0][0])).toBe(
`<div class="test">0</div>`,
)
expect(props.onAfterLeave).not.toHaveBeenCalled()
// enter should not have started
expect(props.onBeforeEnter).not.toHaveBeenCalled()
expect(props.onEnter).not.toHaveBeenCalled()
expect(props.onAfterEnter).not.toHaveBeenCalled()
cbs.doneLeave[`<div class="test">0</div>`]()
expect(serializeInner(root)).toBe(`<span class="test">0</span>`)
}
await runTestWithKeepAlive(testOutIn)
__DEV__ = true
})
})

View File

@ -10,14 +10,28 @@ import {
markRaw,
nextTick,
nodeOps,
onMounted,
h as originalH,
ref,
render,
serialize,
serializeInner,
withDirectives,
} from '@vue/runtime-test'
import { Fragment, createCommentVNode, createVNode } from '../../src/vnode'
import {
Fragment,
createBlock,
createCommentVNode,
createTextVNode,
createVNode,
openBlock,
} from '../../src/vnode'
import { toDisplayString } from '@vue/shared'
import { compile, createApp as createDOMApp, render as domRender } from 'vue'
import type { HMRRuntime } from '../../src/hmr'
declare var __VUE_HMR_RUNTIME__: HMRRuntime
const { rerender, createRecord } = __VUE_HMR_RUNTIME__
describe('renderer: teleport', () => {
describe('eager mode', () => {
@ -243,6 +257,39 @@ describe('renderer: teleport', () => {
expect(serializeInner(target)).toBe(`teleported`)
})
test('should traverse comment node after updating in optimize mode', async () => {
const target = nodeOps.createElement('div')
const root = nodeOps.createElement('div')
const count = ref(0)
let teleport
__DEV__ = false
render(
h(() => {
teleport =
(openBlock(),
createBlock(Teleport, { to: target }, [
createCommentVNode('comment in teleport'),
]))
return h('div', null, [
createTextVNode(toDisplayString(count.value)),
teleport,
])
}),
root,
)
const commentNode = teleport!.children[0].el
expect(serializeInner(root)).toBe(`<div>0</div>`)
expect(serializeInner(target)).toBe(`<!--comment in teleport-->`)
expect(serialize(commentNode)).toBe(`<!--comment in teleport-->`)
count.value = 1
await nextTick()
__DEV__ = true
expect(serializeInner(root)).toBe(`<div>1</div>`)
expect(teleport!.children[0].el).toBe(commentNode)
})
test('should remove children when unmounted', () => {
const target = nodeOps.createElement('div')
const root = nodeOps.createElement('div')
@ -269,6 +316,34 @@ describe('renderer: teleport', () => {
testUnmount({ to: null, disabled: true })
})
// #10747
test('should unmount correctly when using top level comment in teleport', async () => {
const target = nodeOps.createElement('div')
const root = nodeOps.createElement('div')
const count = ref(0)
__DEV__ = false
render(
h(() => {
return h('div', null, [
createTextVNode(toDisplayString(count.value)),
(openBlock(),
createBlock(Teleport, { to: target }, [
createCommentVNode('comment in teleport'),
])),
])
}),
root,
)
count.value = 1
await nextTick()
__DEV__ = true
render(null, root)
expect(root.children.length).toBe(0)
})
test('component with multi roots should be removed when unmounted', () => {
const target = nodeOps.createElement('div')
const root = nodeOps.createElement('div')
@ -741,4 +816,56 @@ describe('renderer: teleport', () => {
expect(tRefInMounted).toBe(target.children[1])
})
}
test('handle update and hmr rerender', async () => {
const target = document.createElement('div')
const root = document.createElement('div')
const Comp = {
setup() {
const cls = ref('foo')
onMounted(() => {
// trigger update
cls.value = 'bar'
})
return { cls, target }
},
template: `
<Teleport :to="target">
<div :class="cls">
<div>
<slot></slot>
</div>
</div>
</Teleport>
`,
}
const appId = 'test-app-id'
const App = {
__hmrId: appId,
components: { Comp },
render() {
return originalH(Comp, null, { default: () => originalH('div', 'foo') })
},
}
createRecord(appId, App)
domRender(originalH(App), root)
expect(target.innerHTML).toBe(
'<div class="foo"><div><div>foo</div></div></div>',
)
await nextTick()
expect(target.innerHTML).toBe(
'<div class="bar"><div><div>foo</div></div></div>',
)
rerender(appId, () =>
originalH(Comp, null, { default: () => originalH('div', 'bar') }),
)
await nextTick()
expect(target.innerHTML).toBe(
'<div class="bar"><div><div>bar</div></div></div>',
)
})
})

View File

@ -1,4 +1,10 @@
import { isReactive, reactive, shallowReactive } from '../../src/index'
import {
effect,
isReactive,
reactive,
readonly,
shallowReactive,
} from '../../src/index'
import { renderList } from '../../src/helpers/renderList'
describe('renderList', () => {
@ -65,4 +71,31 @@ describe('renderList', () => {
const shallowReactiveArray = shallowReactive([{ foo: 1 }])
expect(renderList(shallowReactiveArray, isReactive)).toEqual([false])
})
it('should not allow mutation', () => {
const arr = readonly(reactive([{ foo: 1 }]))
expect(
renderList(arr, item => {
;(item as any).foo = 0
return item.foo
}),
).toEqual([1])
expect(
`Set operation on key "foo" failed: target is readonly.`,
).toHaveBeenWarned()
})
it('should trigger effect for deep mutations in readonly reactive arrays', () => {
const arr = reactive([{ foo: 1 }])
const readonlyArr = readonly(arr)
let dummy
effect(() => {
dummy = renderList(readonlyArr, item => item.foo)
})
expect(dummy).toEqual([1])
arr[0].foo = 2
expect(dummy).toEqual([2])
})
})

View File

@ -32,10 +32,13 @@ import {
withCtx,
withDirectives,
} from '@vue/runtime-dom'
import type { HMRRuntime } from '../src/hmr'
import { type SSRContext, renderToString } from '@vue/server-renderer'
import { PatchFlags, normalizeStyle } from '@vue/shared'
import { vShowOriginalDisplay } from '../../runtime-dom/src/directives/vShow'
import { expect } from 'vitest'
declare var __VUE_HMR_RUNTIME__: HMRRuntime
const { createRecord, reload } = __VUE_HMR_RUNTIME__
function mountWithHydration(html: string, render: () => any) {
const container = document.createElement('div')
@ -1843,6 +1846,60 @@ describe('SSR hydration', () => {
}
})
test('hmr reload child wrapped in KeepAlive', async () => {
const id = 'child-reload'
const Child = {
__hmrId: id,
template: `<div>foo</div>`,
}
createRecord(id, Child)
const appId = 'test-app-id'
const App = {
__hmrId: appId,
components: { Child },
template: `
<div>
<KeepAlive>
<Child />
</KeepAlive>
</div>
`,
}
const root = document.createElement('div')
root.innerHTML = await renderToString(h(App))
createSSRApp(App).mount(root)
expect(root.innerHTML).toBe('<div><div>foo</div></div>')
reload(id, {
__hmrId: id,
template: `<div>bar</div>`,
})
await nextTick()
expect(root.innerHTML).toBe('<div><div>bar</div></div>')
})
test('hmr root reload', async () => {
const appId = 'test-app-id'
const App = {
__hmrId: appId,
template: `<div>foo</div>`,
}
const root = document.createElement('div')
root.innerHTML = await renderToString(h(App))
createSSRApp(App).mount(root)
expect(root.innerHTML).toBe('<div>foo</div>')
reload(appId, {
__hmrId: appId,
template: `<div>bar</div>`,
})
await nextTick()
expect(root.innerHTML).toBe('<div>bar</div>')
})
describe('mismatch handling', () => {
test('text node', () => {
const { container } = mountWithHydration(`foo`, () => 'bar')

View File

@ -1,6 +1,6 @@
{
"name": "@vue/runtime-core",
"version": "3.5.13",
"version": "3.5.14",
"description": "@vue/runtime-core",
"main": "index.js",
"module": "dist/runtime-core.esm-bundler.js",

View File

@ -837,7 +837,7 @@ export function setupComponent(
vi(instance)
} else {
initProps(instance, props, isStateful, isSSR)
initSlots(instance, children, optimized)
initSlots(instance, children, optimized || isSSR)
}
const setupResult = isStateful

View File

@ -17,7 +17,11 @@ import {
} from '@vue/shared'
import { warn } from './warning'
import { isKeepAlive } from './components/KeepAlive'
import { type ContextualRenderFn, withCtx } from './componentRenderContext'
import {
type ContextualRenderFn,
currentRenderingInstance,
withCtx,
} from './componentRenderContext'
import { isHmrUpdating } from './hmr'
import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'
import { TriggerOpTypes, trigger } from '@vue/reactivity'
@ -75,6 +79,11 @@ export type RawSlots = {
* @internal
*/
_?: SlotFlags
/**
* cache indexes for slot content
* @internal
*/
__?: number[]
}
const isInternalKey = (key: string) => key[0] === '_' || key === '$stable'
@ -98,7 +107,8 @@ const normalizeSlot = (
__DEV__ &&
currentInstance &&
!currentInstance.vapor &&
(!ctx || ctx.root === (currentInstance as ComponentInternalInstance).root)
!(ctx === null && currentRenderingInstance) &&
!(ctx && ctx.root !== currentInstance.root)
) {
warn(
`Slot "${key}" invoked outside of the render function: ` +
@ -171,7 +181,7 @@ const assignSlots = (
// when rendering the optimized slots by manually written render function,
// do not copy the `slots._` compiler flag so that `renderSlot` creates
// slot Fragment with BAIL patchFlag to force full updates
if (optimized || key !== '_') {
if (optimized || !isInternalKey(key)) {
slots[key] = children[key]
}
}

View File

@ -501,9 +501,8 @@ function getInnerChild(vnode: VNode): VNode | undefined {
return vnode
}
// #7121 ensure get the child component subtree in case
// it's been replaced during HMR
if (__DEV__ && vnode.component) {
// #7121,#12465 get the component subtree if it's been mounted
if (vnode.component) {
return vnode.component.subTree
}

View File

@ -220,7 +220,8 @@ export const TeleportImpl = {
// even in block tree mode we need to make sure all root-level nodes
// in the teleport inherit previous DOM references so that they can
// be moved in future patches.
traverseStaticChildren(n1, n2, true)
// in dev mode, deep traversal is necessary for HMR
traverseStaticChildren(n1, n2, !__DEV__)
} else if (!optimized) {
patchChildren(
n1,

View File

@ -1,9 +1,11 @@
import type { VNode, VNodeChild } from '../vnode'
import {
isReactive,
isReadonly,
isShallow,
shallowReadArray,
toReactive,
toReadonly,
} from '@vue/reactivity'
import { isArray, isObject, isString } from '@vue/shared'
import { warn } from '../warning'
@ -69,14 +71,20 @@ export function renderList(
if (sourceIsArray || isString(source)) {
const sourceIsReactiveArray = sourceIsArray && isReactive(source)
let needsWrap = false
let isReadonlySource = false
if (sourceIsReactiveArray) {
needsWrap = !isShallow(source)
isReadonlySource = isReadonly(source)
source = shallowReadArray(source)
}
ret = new Array(source.length)
for (let i = 0, l = source.length; i < l; i++) {
ret[i] = renderItem(
needsWrap ? toReactive(source[i]) : source[i],
needsWrap
? isReadonlySource
? toReadonly(toReactive(source[i]))
: toReactive(source[i])
: source[i],
i,
undefined,
cached && cached[i],

View File

@ -1248,12 +1248,12 @@ function baseCreateRenderer(
}
}
// avoid hydration for hmr updating
if (__DEV__ && isHmrUpdating) initialVNode.el = null
// setup() is async. This component relies on async logic to be resolved
// before proceeding
if (__FEATURE_SUSPENSE__ && instance.asyncDep) {
// avoid hydration for hmr updating
if (__DEV__ && isHmrUpdating) initialVNode.el = null
parentSuspense &&
parentSuspense.registerDep(instance, setupRenderEffect, optimized)
@ -2169,7 +2169,9 @@ function baseCreateRenderer(
// unset ref
if (ref != null) {
pauseTracking()
setRef(ref, null, parentSuspense, vnode, true)
resetTracking()
}
// #6593 should clean memo cache when unmount
@ -2343,7 +2345,17 @@ function baseCreateRenderer(
unregisterHMR(instance)
}
const { bum, scope, job, subTree, um, m, a } = instance
const {
bum,
scope,
job,
subTree,
um,
m,
a,
parent,
slots: { __: slotCacheKeys },
} = instance
invalidateMount(m)
invalidateMount(a)
@ -2352,6 +2364,13 @@ function baseCreateRenderer(
invokeArrayFns(bum)
}
// remove slots content from parent renderCache
if (parent && isArray(slotCacheKeys)) {
slotCacheKeys.forEach(v => {
;(parent as ComponentInternalInstance).renderCache[v] = undefined
})
}
if (
__COMPAT__ &&
isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)
@ -2502,9 +2521,12 @@ function baseCreateRenderer(
// HMR root reload
if (__DEV__) {
app._context.reload = () => {
const cloned = cloneVNode(vnode)
// avoid hydration for hmr updating
cloned.el = null
// casting to ElementNamespace because TS doesn't guarantee type narrowing
// over function boundaries
render(cloneVNode(vnode), container, namespace as ElementNamespace)
render(cloned, container, namespace as ElementNamespace)
}
}
@ -2610,11 +2632,15 @@ export function traverseStaticChildren(
if (c2.type === Text) {
c2.el = c1.el
}
// also inherit for comment nodes, but not placeholders (e.g. v-if which
// #2324 also inherit for comment nodes, but not placeholders (e.g. v-if which
// would have received .el during block patch)
if (__DEV__ && c2.type === Comment && !c2.el) {
if (c2.type === Comment && !c2.el) {
c2.el = c1.el
}
if (__DEV__) {
c2.el && (c2.el.__vnode = c2)
}
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@vue/runtime-dom",
"version": "3.5.13",
"version": "3.5.14",
"description": "@vue/runtime-dom",
"main": "index.js",
"module": "dist/runtime-dom.esm-bundler.js",

View File

@ -82,6 +82,7 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({
moveClass,
)
) {
prevChildren = []
return
}
@ -111,6 +112,7 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({
})
el.addEventListener('transitionend', cb)
})
prevChildren = []
})
return () => {

View File

@ -1,4 +1,4 @@
import { createApp } from 'vue'
import { createApp, defineAsyncComponent, h } from 'vue'
import { renderToString } from '../src/renderToString'
const components = {
@ -154,6 +154,38 @@ describe('ssr: slot', () => {
).toBe(`<div><p>1</p><p>2</p></div>`)
})
// #12438
test('async component slot with v-if true', async () => {
const Layout = defineAsyncComponent(() =>
Promise.resolve({
template: `<div><slot name="header">default header</slot></div>`,
}),
)
const LayoutLoader = {
setup(_: any, context: any) {
return () => h(Layout, {}, context.slots)
},
}
expect(
await renderToString(
createApp({
components: {
LayoutLoader,
},
template: `
<Suspense>
<LayoutLoader>
<template v-if="true" #header>
new header
</template>
</LayoutLoader>
</Suspense>
`,
}),
),
).toBe(`<div><!--[--> new header <!--]--></div>`)
})
// #11326
test('dynamic component slot', async () => {
expect(

View File

@ -1,6 +1,6 @@
{
"name": "@vue/server-renderer",
"version": "3.5.13",
"version": "3.5.14",
"description": "@vue/server-renderer",
"main": "index.js",
"module": "dist/server-renderer.esm-bundler.js",

View File

@ -1,6 +1,6 @@
{
"name": "@vue/shared",
"version": "3.5.13",
"version": "3.5.14",
"description": "internal utils shared across @vue packages",
"main": "index.js",
"module": "dist/shared.esm-bundler.js",

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compat",
"version": "3.5.13",
"version": "3.5.14",
"description": "Vue 3 compatibility build for Vue 2",
"main": "index.js",
"module": "dist/vue.runtime.esm-bundler.js",

View File

@ -647,4 +647,55 @@ describe('e2e: TransitionGroup', () => {
},
E2E_TIMEOUT,
)
test(
'not leaking after children unmounted',
async () => {
const client = await page().createCDPSession()
await page().evaluate(async () => {
const { createApp, ref, nextTick } = (window as any).Vue
const show = ref(true)
createApp({
components: {
Child: {
setup: () => {
// Big arrays kick GC earlier
const test = ref([...Array(3000)].map((_, i) => ({ i })))
// @ts-expect-error - Custom property and same lib as runtime is used
window.__REF__ = new WeakRef(test)
return { test }
},
template: `
<p>{{ test.length }}</p>
`,
},
},
template: `
<transition-group>
<Child v-if="show" />
</transition-group>
`,
setup() {
return { show }
},
}).mount('#app')
show.value = false
await nextTick()
})
const isCollected = async () =>
// @ts-expect-error - Custom property
await page().evaluate(() => window.__REF__.deref() === undefined)
while ((await isCollected()) === false) {
await client.send('HeapProfiler.collectGarbage')
}
expect(await isCollected()).toBe(true)
},
E2E_TIMEOUT,
)
})

View File

@ -1,6 +1,6 @@
{
"name": "vue",
"version": "3.5.13",
"version": "3.5.14",
"description": "The progressive JavaScript framework for building modern web UI.",
"main": "index.js",
"module": "dist/vue.runtime.esm-bundler.js",

View File

@ -7,14 +7,14 @@ settings:
catalogs:
default:
'@babel/parser':
specifier: ^7.27.0
specifier: ^7.27.2
version: 7.27.5
'@babel/types':
specifier: ^7.27.0
specifier: ^7.27.1
version: 7.27.6
'@vitejs/plugin-vue':
specifier: https://pkg.pr.new/@vitejs/plugin-vue@c156992
version: 5.2.1
specifier: ^5.2.4
version: 5.2.4
estree-walker:
specifier: ^2.0.2
version: 2.0.2
@ -54,13 +54,13 @@ importers:
specifier: 5.0.4
version: 5.0.4(rollup@4.43.0)
'@swc/core':
specifier: ^1.11.13
specifier: ^1.11.24
version: 1.12.1
'@types/hash-sum':
specifier: ^1.0.2
version: 1.0.2
'@types/node':
specifier: ^22.13.14
specifier: ^22.14.1
version: 22.15.32
'@types/semver':
specifier: ^7.7.0
@ -69,10 +69,10 @@ importers:
specifier: ^6.1.4
version: 6.1.4
'@vitest/coverage-v8':
specifier: ^3.0.9
specifier: ^3.1.3
version: 3.2.4(vitest@3.2.4)
'@vitest/eslint-plugin':
specifier: ^1.1.38
specifier: ^1.1.44
version: 1.2.7(eslint@9.29.0)(typescript@5.6.3)(vitest@3.2.4)
'@vitest/ui':
specifier: ^3.0.2
@ -87,25 +87,25 @@ importers:
specifier: ^2.4.1
version: 2.4.1
esbuild:
specifier: ^0.25.2
specifier: ^0.25.4
version: 0.25.5
esbuild-plugin-polyfill-node:
specifier: ^0.3.0
version: 0.3.0(esbuild@0.25.5)
eslint:
specifier: ^9.23.0
specifier: ^9.25.1
version: 9.29.0
eslint-plugin-import-x:
specifier: ^4.9.4
specifier: ^4.11.0
version: 4.15.2(@typescript-eslint/utils@8.34.1(eslint@9.29.0)(typescript@5.6.3))(eslint@9.29.0)
estree-walker:
specifier: 'catalog:'
version: 2.0.2
jsdom:
specifier: ^26.0.0
specifier: ^26.1.0
version: 26.1.0
lint-staged:
specifier: ^15.5.0
specifier: ^15.5.1
version: 15.5.2
lodash:
specifier: ^4.17.21
@ -135,13 +135,13 @@ importers:
specifier: ^3.0.3
version: 3.0.3
puppeteer:
specifier: ~24.4.0
version: 24.4.0(typescript@5.6.3)
specifier: ~24.8.2
version: 24.8.2(typescript@5.6.3)
rimraf:
specifier: ^6.0.1
version: 6.0.1
rollup:
specifier: ^4.38.0
specifier: ^4.40.2
version: 4.43.0
rollup-plugin-dts:
specifier: ^6.2.1
@ -162,7 +162,7 @@ importers:
specifier: ^6.1.6
version: 6.1.6
simple-git-hooks:
specifier: ^2.12.1
specifier: ^2.13.0
version: 2.13.0
todomvc-app-css:
specifier: ^2.4.3
@ -174,20 +174,20 @@ importers:
specifier: ~5.6.2
version: 5.6.3
typescript-eslint:
specifier: ^8.28.0
specifier: ^8.31.1
version: 8.34.1(eslint@9.29.0)(typescript@5.6.3)
vite:
specifier: 'catalog:'
version: 6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0)
vitest:
specifier: ^3.0.9
specifier: ^3.1.3
version: 3.2.4(@types/node@22.15.32)(@vitest/ui@3.2.4)(jsdom@26.1.0)(sass@1.89.2)(yaml@2.8.0)
packages-private/benchmark:
dependencies:
'@vitejs/plugin-vue':
specifier: 'catalog:'
version: https://pkg.pr.new/@vitejs/plugin-vue@c156992(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@3.5.13(typescript@5.6.3))
version: 5.2.4(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@3.5.14(typescript@5.6.3))
connect:
specifier: ^3.7.0
version: 3.7.0
@ -234,7 +234,7 @@ importers:
devDependencies:
'@vitejs/plugin-vue':
specifier: 'catalog:'
version: https://pkg.pr.new/@vitejs/plugin-vue@c156992(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)
version: 5.2.4(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)
'@vue/compiler-sfc':
specifier: workspace:*
version: link:../../packages/compiler-sfc
@ -265,7 +265,7 @@ importers:
devDependencies:
'@vitejs/plugin-vue':
specifier: 'catalog:'
version: https://pkg.pr.new/@vitejs/plugin-vue@c156992(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)
version: 5.2.4(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)
vite:
specifier: 'catalog:'
version: 6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0)
@ -289,7 +289,7 @@ importers:
version: 3.4.38
'@vitejs/plugin-vue':
specifier: 'catalog:'
version: https://pkg.pr.new/@vitejs/plugin-vue@c156992(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)
version: 5.2.4(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)
connect:
specifier: ^3.7.0
version: 3.7.0
@ -307,7 +307,7 @@ importers:
devDependencies:
'@vitejs/plugin-vue':
specifier: 'catalog:'
version: https://pkg.pr.new/@vitejs/plugin-vue@c156992(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)
version: 5.2.4(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)
vite:
specifier: 'catalog:'
version: 6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0)
@ -407,7 +407,7 @@ importers:
specifier: ^3.0.3
version: 3.0.3
sass:
specifier: ^1.86.0
specifier: ^1.86.3
version: 1.89.2
packages/compiler-ssr:
@ -1120,8 +1120,8 @@ packages:
'@polka/url@1.0.0-next.29':
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
'@puppeteer/browsers@2.8.0':
resolution: {integrity: sha512-yTwt2KWRmCQAfhvbCRjebaSX8pV1//I0Y3g+A7f/eS7gf0l4eRJoUCvcYdVtboeU4CTOZQuqYbZNS8aBYb8ROQ==}
'@puppeteer/browsers@2.10.4':
resolution: {integrity: sha512-9DxbZx+XGMNdjBynIs4BRSz+M3iRDeB7qRcAr6UORFLphCIM2x3DXgOucvADiifcqCE4XePFUKcnaAMyGbrDlQ==}
engines: {node: '>=18'}
hasBin: true
@ -1568,9 +1568,8 @@ packages:
cpu: [x64]
os: [win32]
'@vitejs/plugin-vue@https://pkg.pr.new/@vitejs/plugin-vue@c156992':
resolution: {tarball: https://pkg.pr.new/@vitejs/plugin-vue@c156992}
version: 5.2.1
'@vitejs/plugin-vue@5.2.4':
resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==}
engines: {node: ^18.0.0 || >=20.0.0}
peerDependencies:
vite: ^5.0.0 || ^6.0.0
@ -1631,41 +1630,41 @@ packages:
'@vitest/utils@3.2.4':
resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
'@vue/compiler-core@3.5.13':
resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==}
'@vue/compiler-core@3.5.14':
resolution: {integrity: sha512-k7qMHMbKvoCXIxPhquKQVw3Twid3Kg4s7+oYURxLGRd56LiuHJVrvFKI4fm2AM3c8apqODPfVJGoh8nePbXMRA==}
'@vue/compiler-dom@3.5.13':
resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==}
'@vue/compiler-dom@3.5.14':
resolution: {integrity: sha512-1aOCSqxGOea5I80U2hQJvXYpPm/aXo95xL/m/mMhgyPUsKe9jhjwWpziNAw7tYRnbz1I61rd9Mld4W9KmmRoug==}
'@vue/compiler-sfc@3.5.13':
resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==}
'@vue/compiler-sfc@3.5.14':
resolution: {integrity: sha512-9T6m/9mMr81Lj58JpzsiSIjBgv2LiVoWjIVa7kuXHICUi8LiDSIotMpPRXYJsXKqyARrzjT24NAwttrMnMaCXA==}
'@vue/compiler-ssr@3.5.13':
resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==}
'@vue/compiler-ssr@3.5.14':
resolution: {integrity: sha512-Y0G7PcBxr1yllnHuS/NxNCSPWnRGH4Ogrp0tsLA5QemDZuJLs99YjAKQ7KqkHE0vCg4QTKlQzXLKCMF7WPSl7Q==}
'@vue/consolidate@1.0.0':
resolution: {integrity: sha512-oTyUE+QHIzLw2PpV14GD/c7EohDyP64xCniWTcqcEmTd699eFqTIwOmtDYjcO1j3QgdXoJEoWv1/cCdLrRoOfg==}
engines: {node: '>= 0.12.0'}
'@vue/reactivity@3.5.13':
resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==}
'@vue/reactivity@3.5.14':
resolution: {integrity: sha512-7cK1Hp343Fu/SUCCO52vCabjvsYu7ZkOqyYu7bXV9P2yyfjUMUXHZafEbq244sP7gf+EZEz+77QixBTuEqkQQw==}
'@vue/repl@4.6.1':
resolution: {integrity: sha512-tgeEa+QXzqbFsAIbq/dCXzOJxIW2Nq1F79KXRjbKyPt1ODpCx86bDbFgNzFcBEK3In2/mjPTMpN7fSD6Ig0Qsw==}
'@vue/runtime-core@3.5.13':
resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==}
'@vue/runtime-core@3.5.14':
resolution: {integrity: sha512-w9JWEANwHXNgieAhxPpEpJa+0V5G0hz3NmjAZwlOebtfKyp2hKxKF0+qSh0Xs6/PhfGihuSdqMprMVcQU/E6ag==}
'@vue/runtime-dom@3.5.13':
resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==}
'@vue/runtime-dom@3.5.14':
resolution: {integrity: sha512-lCfR++IakeI35TVR80QgOelsUIdcKjd65rWAMfdSlCYnaEY5t3hYwru7vvcWaqmrK+LpI7ZDDYiGU5V3xjMacw==}
'@vue/server-renderer@3.5.13':
resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==}
'@vue/server-renderer@3.5.14':
resolution: {integrity: sha512-Rf/ISLqokIvcySIYnv3tNWq40PLpNLDLSJwwVWzG6MNtyIhfbcrAxo5ZL9nARJhqjZyWWa40oRb2IDuejeuv6w==}
peerDependencies:
vue: 3.5.13
vue: 3.5.14
'@vue/shared@3.5.13':
resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==}
'@vue/shared@3.5.14':
resolution: {integrity: sha512-oXTwNxVfc9EtP1zzXAlSlgARLXNC84frFYkS0HHz0h3E4WZSP9sywqjqzGCP9Y34M8ipNmd380pVgmMuwELDyQ==}
'@vueuse/core@11.3.0':
resolution: {integrity: sha512-7OC4Rl1f9G8IT6rUfi9JrKiXy4bfmHhZ5x2Ceojy0jnd3mHNEvV4JaRygH362ror6/NZ+Nl+n13LPzGiPN8cKA==}
@ -1887,8 +1886,8 @@ packages:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
chromium-bidi@2.1.2:
resolution: {integrity: sha512-vtRWBK2uImo5/W2oG6/cDkkHSm+2t6VHgnj+Rcwhb0pP74OoUb4GipyRX/T/y39gYQPhioP0DPShn+A7P6CHNw==}
chromium-bidi@5.1.0:
resolution: {integrity: sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==}
peerDependencies:
devtools-protocol: '*'
@ -2117,8 +2116,8 @@ packages:
engines: {node: '>=0.10'}
hasBin: true
devtools-protocol@0.0.1413902:
resolution: {integrity: sha512-yRtvFD8Oyk7C9Os3GmnFZLu53yAfsnyw1s+mLmHHUK0GQEc9zthHWvS1r67Zqzm5t7v56PILHIVZ7kmFMaL2yQ==}
devtools-protocol@0.0.1439962:
resolution: {integrity: sha512-jJF48UdryzKiWhJ1bLKr7BFWUQCEIT5uCNbDLqkQJBtkFxYzILJH44WN0PDKMIlGDN7Utb8vyUY85C3w4R/t2g==}
doctypes@1.1.0:
resolution: {integrity: sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==}
@ -3229,12 +3228,12 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
puppeteer-core@24.4.0:
resolution: {integrity: sha512-eFw66gCnWo0X8Hyf9KxxJtms7a61NJVMiSaWfItsFPzFBsjsWdmcNlBdsA1WVwln6neoHhsG+uTVesKmTREn/g==}
puppeteer-core@24.8.2:
resolution: {integrity: sha512-wNw5cRZOHiFibWc0vdYCYO92QuKTbJ8frXiUfOq/UGJWMqhPoBThTKkV+dJ99YyWfzJ2CfQQ4T1nhhR0h8FlVw==}
engines: {node: '>=18'}
puppeteer@24.4.0:
resolution: {integrity: sha512-E4JhJzjS8AAI+6N/b+Utwarhz6zWl3+MR725fal+s3UlOlX2eWdsvYYU+Q5bXMjs9eZEGkNQroLkn7j11s2k1Q==}
puppeteer@24.8.2:
resolution: {integrity: sha512-Sn6SBPwJ6ASFvQ7knQkR+yG7pcmr4LfXzmoVp3NR0xXyBbPhJa8a8ybtb6fnw1g/DD/2t34//yirubVczko37w==}
engines: {node: '>=18'}
hasBin: true
@ -3829,8 +3828,8 @@ packages:
'@vue/composition-api':
optional: true
vue@3.5.13:
resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==}
vue@3.5.14:
resolution: {integrity: sha512-LbOm50/vZFG6Mhy6KscQYXZMQ0LMCC/y40HDJPPvGFQ+i/lUH+PJHR6C3assgOQiXdl6tAfsXHbXYVBZZu65ew==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
@ -4358,7 +4357,7 @@ snapshots:
'@polka/url@1.0.0-next.29': {}
'@puppeteer/browsers@2.8.0':
'@puppeteer/browsers@2.10.4':
dependencies:
debug: 4.4.1
extract-zip: 2.0.1
@ -4737,12 +4736,12 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.9.0':
optional: true
'@vitejs/plugin-vue@https://pkg.pr.new/@vitejs/plugin-vue@c156992(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@3.5.13(typescript@5.6.3))':
'@vitejs/plugin-vue@5.2.4(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@3.5.14(typescript@5.6.3))':
dependencies:
vite: 6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0)
vue: 3.5.13(typescript@5.6.3)
vue: 3.5.14(typescript@5.6.3)
'@vitejs/plugin-vue@https://pkg.pr.new/@vitejs/plugin-vue@c156992(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)':
'@vitejs/plugin-vue@5.2.4(vite@6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0))(vue@packages+vue)':
dependencies:
vite: 6.3.5(@types/node@22.15.32)(sass@1.89.2)(yaml@2.8.0)
vue: link:packages/vue
@ -4829,63 +4828,63 @@ snapshots:
loupe: 3.1.4
tinyrainbow: 2.0.0
'@vue/compiler-core@3.5.13':
'@vue/compiler-core@3.5.14':
dependencies:
'@babel/parser': 7.27.5
'@vue/shared': 3.5.13
'@vue/shared': 3.5.14
entities: 4.5.0
estree-walker: 2.0.2
source-map-js: 1.2.1
'@vue/compiler-dom@3.5.13':
'@vue/compiler-dom@3.5.14':
dependencies:
'@vue/compiler-core': 3.5.13
'@vue/shared': 3.5.13
'@vue/compiler-core': 3.5.14
'@vue/shared': 3.5.14
'@vue/compiler-sfc@3.5.13':
'@vue/compiler-sfc@3.5.14':
dependencies:
'@babel/parser': 7.27.5
'@vue/compiler-core': 3.5.13
'@vue/compiler-dom': 3.5.13
'@vue/compiler-ssr': 3.5.13
'@vue/shared': 3.5.13
'@vue/compiler-core': 3.5.14
'@vue/compiler-dom': 3.5.14
'@vue/compiler-ssr': 3.5.14
'@vue/shared': 3.5.14
estree-walker: 2.0.2
magic-string: 0.30.17
postcss: 8.5.6
source-map-js: 1.2.1
'@vue/compiler-ssr@3.5.13':
'@vue/compiler-ssr@3.5.14':
dependencies:
'@vue/compiler-dom': 3.5.13
'@vue/shared': 3.5.13
'@vue/compiler-dom': 3.5.14
'@vue/shared': 3.5.14
'@vue/consolidate@1.0.0': {}
'@vue/reactivity@3.5.13':
'@vue/reactivity@3.5.14':
dependencies:
'@vue/shared': 3.5.13
'@vue/shared': 3.5.14
'@vue/repl@4.6.1': {}
'@vue/runtime-core@3.5.13':
'@vue/runtime-core@3.5.14':
dependencies:
'@vue/reactivity': 3.5.13
'@vue/shared': 3.5.13
'@vue/reactivity': 3.5.14
'@vue/shared': 3.5.14
'@vue/runtime-dom@3.5.13':
'@vue/runtime-dom@3.5.14':
dependencies:
'@vue/reactivity': 3.5.13
'@vue/runtime-core': 3.5.13
'@vue/shared': 3.5.13
'@vue/reactivity': 3.5.14
'@vue/runtime-core': 3.5.14
'@vue/shared': 3.5.14
csstype: 3.1.3
'@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.6.3))':
'@vue/server-renderer@3.5.14(vue@3.5.14(typescript@5.6.3))':
dependencies:
'@vue/compiler-ssr': 3.5.13
'@vue/shared': 3.5.13
vue: 3.5.13(typescript@5.6.3)
'@vue/compiler-ssr': 3.5.14
'@vue/shared': 3.5.14
vue: 3.5.14(typescript@5.6.3)
'@vue/shared@3.5.13': {}
'@vue/shared@3.5.14': {}
'@vueuse/core@11.3.0(vue@packages+vue)':
dependencies:
@ -5097,9 +5096,9 @@ snapshots:
dependencies:
readdirp: 4.1.2
chromium-bidi@2.1.2(devtools-protocol@0.0.1413902):
chromium-bidi@5.1.0(devtools-protocol@0.0.1439962):
dependencies:
devtools-protocol: 0.0.1413902
devtools-protocol: 0.0.1439962
mitt: 3.0.1
zod: 3.25.67
@ -5327,7 +5326,7 @@ snapshots:
detect-libc@1.0.3:
optional: true
devtools-protocol@0.0.1413902: {}
devtools-protocol@0.0.1439962: {}
doctypes@1.1.0: {}
@ -6516,12 +6515,12 @@ snapshots:
punycode@2.3.1: {}
puppeteer-core@24.4.0:
puppeteer-core@24.8.2:
dependencies:
'@puppeteer/browsers': 2.8.0
chromium-bidi: 2.1.2(devtools-protocol@0.0.1413902)
'@puppeteer/browsers': 2.10.4
chromium-bidi: 5.1.0(devtools-protocol@0.0.1439962)
debug: 4.4.1
devtools-protocol: 0.0.1413902
devtools-protocol: 0.0.1439962
typed-query-selector: 2.12.0
ws: 8.18.2
transitivePeerDependencies:
@ -6530,13 +6529,13 @@ snapshots:
- supports-color
- utf-8-validate
puppeteer@24.4.0(typescript@5.6.3):
puppeteer@24.8.2(typescript@5.6.3):
dependencies:
'@puppeteer/browsers': 2.8.0
chromium-bidi: 2.1.2(devtools-protocol@0.0.1413902)
'@puppeteer/browsers': 2.10.4
chromium-bidi: 5.1.0(devtools-protocol@0.0.1439962)
cosmiconfig: 9.0.0(typescript@5.6.3)
devtools-protocol: 0.0.1413902
puppeteer-core: 24.4.0
devtools-protocol: 0.0.1439962
puppeteer-core: 24.8.2
typed-query-selector: 2.12.0
transitivePeerDependencies:
- bare-buffer
@ -7176,13 +7175,13 @@ snapshots:
dependencies:
vue: link:packages/vue
vue@3.5.13(typescript@5.6.3):
vue@3.5.14(typescript@5.6.3):
dependencies:
'@vue/compiler-dom': 3.5.13
'@vue/compiler-sfc': 3.5.13
'@vue/runtime-dom': 3.5.13
'@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.6.3))
'@vue/shared': 3.5.13
'@vue/compiler-dom': 3.5.14
'@vue/compiler-sfc': 3.5.14
'@vue/runtime-dom': 3.5.14
'@vue/server-renderer': 3.5.14(vue@3.5.14(typescript@5.6.3))
'@vue/shared': 3.5.14
optionalDependencies:
typescript: 5.6.3

View File

@ -3,10 +3,25 @@ packages:
- 'packages-private/*'
catalog:
'@babel/parser': ^7.27.0
'@babel/types': ^7.27.0
'@babel/parser': ^7.27.2
'@babel/types': ^7.27.1
'estree-walker': ^2.0.2
'vite': ^6.1.0
'@vitejs/plugin-vue': https://pkg.pr.new/@vitejs/plugin-vue@c156992
'@vitejs/plugin-vue': ^5.2.4
'magic-string': ^0.30.17
'source-map-js': ^1.2.1
onlyBuiltDependencies:
- '@swc/core'
- 'esbuild'
- 'puppeteer'
- 'simple-git-hooks'
- 'unrs-resolver'
peerDependencyRules:
allowedVersions:
'typescript-eslint>eslint': '^9.0.0'
'@typescript-eslint/eslint-plugin>eslint': '^9.0.0'
'@typescript-eslint/parser>eslint': '^9.0.0'
'@typescript-eslint/type-utils>eslint': '^9.0.0'
'@typescript-eslint/utils>eslint': '^9.0.0'