diff --git a/CHANGELOG.md b/CHANGELOG.md
index 28a30bfa8c4..9f345f8fe75 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+## [3.5.3](https://github.com/vuejs/core/compare/v3.5.2...v3.5.3) (2024-09-06)
+
+
+### Bug Fixes
+
+* **hydration:** check __asyncHydrate presence for vue3-lazy-hydration compat ([#11825](https://github.com/vuejs/core/issues/11825)) ([8e6c337](https://github.com/vuejs/core/commit/8e6c3378676be05cea7f53664442acdfb86784f9)), closes [#11793](https://github.com/vuejs/core/issues/11793)
+* Revert "fix(reactivity): self-referencing computed should refresh" ([35c760f](https://github.com/vuejs/core/commit/35c760f82f749f7c6e3f9bfead8221ce498e892f))
+* **ssr:** respect app.config.warnHandler during ssr ([bf3d9a2](https://github.com/vuejs/core/commit/bf3d9a2af41659a743706306fc798b3d215df5af)), closes [#11830](https://github.com/vuejs/core/issues/11830)
+* **Transition:** handle KeepAlive child unmount in Transition out-in mode ([#11833](https://github.com/vuejs/core/issues/11833)) ([6b7901d](https://github.com/vuejs/core/commit/6b7901d28ed3a6a9242c666cc1b8e3c0b0b0fe62)), closes [#11775](https://github.com/vuejs/core/issues/11775)
+* **useId:** make generated IDs selector compatible ([babfb4c](https://github.com/vuejs/core/commit/babfb4cbcbf98601d76c1d7653eae8d250ce2710)), closes [#11828](https://github.com/vuejs/core/issues/11828)
+
+
+
## [3.5.2](https://github.com/vuejs/core/compare/v3.5.1...v3.5.2) (2024-09-05)
diff --git a/package.json b/package.json
index 3090d82b669..062fbdb23b4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"private": true,
- "version": "3.5.2",
+ "version": "3.5.3",
"packageManager": "pnpm@9.9.0",
"type": "module",
"scripts": {
diff --git a/packages/compiler-core/package.json b/packages/compiler-core/package.json
index 6f1ba3f8986..da4e3388e02 100644
--- a/packages/compiler-core/package.json
+++ b/packages/compiler-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-core",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "@vue/compiler-core",
"main": "index.js",
"module": "dist/compiler-core.esm-bundler.js",
diff --git a/packages/compiler-dom/package.json b/packages/compiler-dom/package.json
index 66e8da0b97e..de4aa7ea86b 100644
--- a/packages/compiler-dom/package.json
+++ b/packages/compiler-dom/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-dom",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "@vue/compiler-dom",
"main": "index.js",
"module": "dist/compiler-dom.esm-bundler.js",
diff --git a/packages/compiler-sfc/package.json b/packages/compiler-sfc/package.json
index fd417236743..6c831a57679 100644
--- a/packages/compiler-sfc/package.json
+++ b/packages/compiler-sfc/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-sfc",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "@vue/compiler-sfc",
"main": "dist/compiler-sfc.cjs.js",
"module": "dist/compiler-sfc.esm-browser.js",
diff --git a/packages/compiler-ssr/package.json b/packages/compiler-ssr/package.json
index e40bb080534..98636adde6e 100644
--- a/packages/compiler-ssr/package.json
+++ b/packages/compiler-ssr/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-ssr",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "@vue/compiler-ssr",
"main": "dist/compiler-ssr.cjs.js",
"types": "dist/compiler-ssr.d.ts",
diff --git a/packages/reactivity/__tests__/computed.spec.ts b/packages/reactivity/__tests__/computed.spec.ts
index e0b47cf56eb..31daef559a8 100644
--- a/packages/reactivity/__tests__/computed.spec.ts
+++ b/packages/reactivity/__tests__/computed.spec.ts
@@ -594,7 +594,7 @@ describe('reactivity/computed', () => {
v.value += ' World'
await nextTick()
- expect(serializeInner(root)).toBe('Hello World World World World')
+ expect(serializeInner(root)).toBe('Hello World World World')
// expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
})
@@ -892,7 +892,7 @@ describe('reactivity/computed', () => {
v.value += ' World'
await nextTick()
expect(serializeInner(root)).toBe(
- 'Hello World World World World | Hello World World World World',
+ 'Hello World World World | Hello World World World',
)
})
@@ -962,7 +962,6 @@ describe('reactivity/computed', () => {
})
})
- // #11797
test('should prevent endless recursion in self-referencing computed getters', async () => {
const Comp = defineComponent({
data() {
@@ -999,7 +998,7 @@ describe('reactivity/computed', () => {
})
const root = nodeOps.createElement('div')
render(h(Comp), root)
- expect(serializeInner(root)).toBe(`Step
Step 1
`)
+ expect(serializeInner(root)).toBe(`Step
`)
triggerEvent(root.children[1] as TestElement, 'click')
await nextTick()
expect(serializeInner(root)).toBe(`Step Step 2
`)
diff --git a/packages/reactivity/package.json b/packages/reactivity/package.json
index 08d3443cefd..8e6f64b4379 100644
--- a/packages/reactivity/package.json
+++ b/packages/reactivity/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/reactivity",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "@vue/reactivity",
"main": "index.js",
"module": "dist/reactivity.esm-bundler.js",
diff --git a/packages/reactivity/src/computed.ts b/packages/reactivity/src/computed.ts
index d2dd67bf97c..aa5d2079061 100644
--- a/packages/reactivity/src/computed.ts
+++ b/packages/reactivity/src/computed.ts
@@ -111,9 +111,9 @@ export class ComputedRefImpl implements Subscriber {
* @internal
*/
notify(): void {
- this.flags |= EffectFlags.DIRTY
// avoid infinite self recursion
if (activeSub !== this) {
+ this.flags |= EffectFlags.DIRTY
this.dep.notify()
} else if (__DEV__) {
// TODO warn
diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts
index 51df32e9969..88493e4e9a9 100644
--- a/packages/reactivity/src/effect.ts
+++ b/packages/reactivity/src/effect.ts
@@ -345,6 +345,9 @@ function isDirty(sub: Subscriber): boolean {
* @internal
*/
export function refreshComputed(computed: ComputedRefImpl): false | undefined {
+ if (computed.flags & EffectFlags.RUNNING) {
+ return false
+ }
if (
computed.flags & EffectFlags.TRACKING &&
!(computed.flags & EffectFlags.DIRTY)
diff --git a/packages/runtime-core/__tests__/helpers/useId.spec.ts b/packages/runtime-core/__tests__/helpers/useId.spec.ts
index 564755e2fd8..d71260cdaff 100644
--- a/packages/runtime-core/__tests__/helpers/useId.spec.ts
+++ b/packages/runtime-core/__tests__/helpers/useId.spec.ts
@@ -59,7 +59,7 @@ describe('useId', () => {
const app = createApp(BasicComponentWithUseId)
return [app, []]
}),
- ).toBe('v:0 v:1')
+ ).toBe('v-0 v-1')
})
test('with config.idPrefix', async () => {
@@ -69,7 +69,7 @@ describe('useId', () => {
app.config.idPrefix = 'foo'
return [app, []]
}),
- ).toBe('foo:0 foo:1')
+ ).toBe('foo-0 foo-1')
})
test('async component', async () => {
@@ -92,9 +92,9 @@ describe('useId', () => {
}
const expected =
- 'v:0 v:1 ' + // root
- 'v:0-0 v:0-1 ' + // inside first async subtree
- 'v:1-0 v:1-1' // inside second async subtree
+ 'v-0 v-1 ' + // root
+ 'v-0-0 v-0-1 ' + // inside first async subtree
+ 'v-1-0 v-1-1' // inside second async subtree
// assert different async resolution order does not affect id stable-ness
expect(await getOutput(() => factory(0, 16))).toBe(expected)
expect(await getOutput(() => factory(16, 0))).toBe(expected)
@@ -137,9 +137,9 @@ describe('useId', () => {
}
const expected =
- 'v:0 v:1 ' + // root
- 'v:0-0 v:0-1 ' + // inside first async subtree
- 'v:1-0 v:1-1' // inside second async subtree
+ 'v-0 v-1 ' + // root
+ 'v-0-0 v-0-1 ' + // inside first async subtree
+ 'v-1-0 v-1-1' // inside second async subtree
// assert different async resolution order does not affect id stable-ness
expect(await getOutput(() => factory(0, 16))).toBe(expected)
expect(await getOutput(() => factory(16, 0))).toBe(expected)
@@ -188,9 +188,9 @@ describe('useId', () => {
const expected =
'' +
- 'v:0 v:1 ' + // root
- 'v:0-0 v:0-1 ' + // inside first async subtree
- 'v:1-0 v:1-1' + // inside second async subtree
+ 'v-0 v-1 ' + // root
+ 'v-0-0 v-0-1 ' + // inside first async subtree
+ 'v-1-0 v-1-1' + // inside second async subtree
'
'
// assert different async resolution order does not affect id stable-ness
expect(await getOutput(() => factory(0, 16))).toBe(expected)
@@ -232,10 +232,10 @@ describe('useId', () => {
}
const expected =
- 'v:0 ' + // One
- 'v:0-0 ' + // Two
- 'v:0-0-0 v:0-0-1 ' + // Three + Three nested in Two
- 'v:0-1' // Three after Two
+ 'v-0 ' + // One
+ 'v-0-0 ' + // Two
+ 'v-0-0-0 v-0-0-1 ' + // Three + Three nested in Two
+ 'v-0-1' // Three after Two
// assert different async resolution order does not affect id stable-ness
expect(await getOutput(() => factory())).toBe(expected)
expect(await getOutput(() => factory())).toBe(expected)
@@ -278,8 +278,8 @@ describe('useId', () => {
const expected =
'' +
- 'v:0 v:1 ' + // root
- 'v:0-0-0 v:0-0-1' + // async component inside async setup
+ 'v-0 v-1 ' + // root
+ 'v-0-0-0 v-0-0-1' + // async component inside async setup
'
'
// assert different async resolution order does not affect id stable-ness
expect(await getOutput(async () => factory(0, 16))).toBe(expected)
diff --git a/packages/runtime-core/package.json b/packages/runtime-core/package.json
index 79f2104f255..fb247fa7c25 100644
--- a/packages/runtime-core/package.json
+++ b/packages/runtime-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/runtime-core",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "@vue/runtime-core",
"main": "index.js",
"module": "dist/runtime-core.esm-bundler.js",
diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts
index 9fe381ff645..a15d18d56bf 100644
--- a/packages/runtime-core/src/componentRenderUtils.ts
+++ b/packages/runtime-core/src/componentRenderUtils.ts
@@ -27,6 +27,7 @@ import {
warnDeprecation,
} from './compat/compatConfig'
import { shallowReadonly } from '@vue/reactivity'
+import { setTransitionHooks } from './components/BaseTransition'
/**
* dev only flag to track whether $attrs was used during render.
@@ -60,7 +61,6 @@ export function renderComponentRoot(
setupState,
ctx,
inheritAttrs,
- isMounted,
} = instance
const prev = setCurrentRenderingInstance(instance)
@@ -254,9 +254,7 @@ export function renderComponentRoot(
`that cannot be animated.`,
)
}
- root.transition = isMounted
- ? vnode.component!.subTree.transition!
- : vnode.transition
+ setTransitionHooks(root, vnode.transition)
}
if (__DEV__ && setRoot) {
diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts
index 568a6382bfe..6ce06d28239 100644
--- a/packages/runtime-core/src/components/BaseTransition.ts
+++ b/packages/runtime-core/src/components/BaseTransition.ts
@@ -516,6 +516,7 @@ function getInnerChild(vnode: VNode): VNode | undefined {
export function setTransitionHooks(vnode: VNode, hooks: TransitionHooks): void {
if (vnode.shapeFlag & ShapeFlags.COMPONENT && vnode.component) {
+ vnode.transition = hooks
setTransitionHooks(vnode.component.subTree, hooks)
} else if (__FEATURE_SUSPENSE__ && vnode.shapeFlag & ShapeFlags.SUSPENSE) {
vnode.ssContent!.transition = hooks.clone(vnode.ssContent!)
diff --git a/packages/runtime-core/src/helpers/useId.ts b/packages/runtime-core/src/helpers/useId.ts
index f4a199e2c39..f7a2b5fc330 100644
--- a/packages/runtime-core/src/helpers/useId.ts
+++ b/packages/runtime-core/src/helpers/useId.ts
@@ -7,7 +7,7 @@ import { warn } from '../warning'
export function useId(): string | undefined {
const i = getCurrentInstance()
if (i) {
- return (i.appContext.config.idPrefix || 'v') + ':' + i.ids[0] + i.ids[1]++
+ return (i.appContext.config.idPrefix || 'v') + '-' + i.ids[0] + i.ids[1]++
} else if (__DEV__) {
warn(
`useId() is called when there is no active component ` +
diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts
index 7f716b5f4e8..3871167b3ee 100644
--- a/packages/runtime-core/src/index.ts
+++ b/packages/runtime-core/src/index.ts
@@ -400,6 +400,7 @@ import { renderComponentRoot } from './componentRenderUtils'
import { setCurrentRenderingInstance } from './componentRenderContext'
import { isVNode, normalizeVNode } from './vnode'
import { ensureValidVNode } from './helpers/renderSlot'
+import { popWarningContext, pushWarningContext } from './warning'
const _ssrUtils: {
createComponentInstance: typeof createComponentInstance
@@ -410,6 +411,8 @@ const _ssrUtils: {
normalizeVNode: typeof normalizeVNode
getComponentPublicInstance: typeof getComponentPublicInstance
ensureValidVNode: typeof ensureValidVNode
+ pushWarningContext: typeof pushWarningContext
+ popWarningContext: typeof popWarningContext
} = {
createComponentInstance,
setupComponent,
@@ -419,6 +422,8 @@ const _ssrUtils: {
normalizeVNode,
getComponentPublicInstance,
ensureValidVNode,
+ pushWarningContext,
+ popWarningContext,
}
/**
diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts
index 11736e9dff2..9b50dca23f9 100644
--- a/packages/runtime-core/src/renderer.ts
+++ b/packages/runtime-core/src/renderer.ts
@@ -1330,7 +1330,10 @@ function baseCreateRenderer(
}
}
- if (isAsyncWrapperVNode) {
+ if (
+ isAsyncWrapperVNode &&
+ (type as ComponentOptions).__asyncHydrate
+ ) {
;(type as ComponentOptions).__asyncHydrate!(
el as Element,
instance,
diff --git a/packages/runtime-dom/package.json b/packages/runtime-dom/package.json
index 6af3be93a10..42f5d6c6e2f 100644
--- a/packages/runtime-dom/package.json
+++ b/packages/runtime-dom/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/runtime-dom",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "@vue/runtime-dom",
"main": "index.js",
"module": "dist/runtime-dom.esm-bundler.js",
diff --git a/packages/server-renderer/__tests__/render.spec.ts b/packages/server-renderer/__tests__/render.spec.ts
index 1b1d6256e8c..d0a5223b2ff 100644
--- a/packages/server-renderer/__tests__/render.spec.ts
+++ b/packages/server-renderer/__tests__/render.spec.ts
@@ -81,6 +81,18 @@ function testRender(type: string, render: typeof renderToString) {
expect(html).toBe(`foo
`)
})
+ test('warnings should be suppressed by app.config.warnHandler', async () => {
+ const app = createApp({
+ render() {
+ return h('div', this.foo)
+ },
+ })
+ app.config.warnHandler = vi.fn()
+ await render(app)
+ expect('not defined on instance').not.toHaveBeenWarned()
+ expect(app.config.warnHandler).toHaveBeenCalledTimes(1)
+ })
+
describe('components', () => {
test('vnode components', async () => {
expect(
diff --git a/packages/server-renderer/package.json b/packages/server-renderer/package.json
index 078493d7689..80639a81dea 100644
--- a/packages/server-renderer/package.json
+++ b/packages/server-renderer/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/server-renderer",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "@vue/server-renderer",
"main": "index.js",
"module": "dist/server-renderer.esm-bundler.js",
diff --git a/packages/server-renderer/src/render.ts b/packages/server-renderer/src/render.ts
index 97179526456..f04080b9c31 100644
--- a/packages/server-renderer/src/render.ts
+++ b/packages/server-renderer/src/render.ts
@@ -35,6 +35,8 @@ const {
setupComponent,
renderComponentRoot,
normalizeVNode,
+ pushWarningContext,
+ popWarningContext,
} = ssrUtils
export type SSRBuffer = SSRBufferItem[] & { hasAsync?: boolean }
@@ -91,8 +93,14 @@ export function renderComponentVNode(
parentComponent: ComponentInternalInstance | null = null,
slotScopeId?: string,
): SSRBuffer | Promise {
- const instance = createComponentInstance(vnode, parentComponent, null)
+ const instance = (vnode.component = createComponentInstance(
+ vnode,
+ parentComponent,
+ null,
+ ))
+ if (__DEV__) pushWarningContext(vnode)
const res = setupComponent(instance, true /* isSSR */)
+ if (__DEV__) popWarningContext()
const hasAsyncSetup = isPromise(res)
let prefetches = instance.sp /* LifecycleHooks.SERVER_PREFETCH */
if (hasAsyncSetup || prefetches) {
@@ -118,6 +126,7 @@ function renderComponentSubTree(
instance: ComponentInternalInstance,
slotScopeId?: string,
): SSRBuffer | Promise {
+ if (__DEV__) pushWarningContext(instance.vnode)
const comp = instance.type as Component
const { getBuffer, push } = createBuffer()
if (isFunction(comp)) {
@@ -207,6 +216,7 @@ function renderComponentSubTree(
push(``)
}
}
+ if (__DEV__) popWarningContext()
return getBuffer()
}
diff --git a/packages/shared/package.json b/packages/shared/package.json
index 3de674cb693..636b6767ec7 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/shared",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "internal utils shared across @vue packages",
"main": "index.js",
"module": "dist/shared.esm-bundler.js",
diff --git a/packages/vue-compat/package.json b/packages/vue-compat/package.json
index 1f0ebbf6c18..4a015d2f4da 100644
--- a/packages/vue-compat/package.json
+++ b/packages/vue-compat/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compat",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "Vue 3 compatibility build for Vue 2",
"main": "index.js",
"module": "dist/vue.runtime.esm-bundler.js",
diff --git a/packages/vue/package.json b/packages/vue/package.json
index 96541cacfac..23fbbfd71fc 100644
--- a/packages/vue/package.json
+++ b/packages/vue/package.json
@@ -1,6 +1,6 @@
{
"name": "vue",
- "version": "3.5.2",
+ "version": "3.5.3",
"description": "The progressive JavaScript framework for building modern web UI.",
"main": "index.js",
"module": "dist/vue.runtime.esm-bundler.js",