diff --git a/CHANGELOG.md b/CHANGELOG.md
index 53a880885..6e787f1a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,20 @@
+# [3.6.0-alpha.2](https://github.com/vuejs/core/compare/v3.6.0-alpha.1...v3.6.0-alpha.2) (2025-07-18)
+
+
+### Bug Fixes
+
+* **compiler-vapor:** handle empty interpolation ([#13592](https://github.com/vuejs/core/issues/13592)) ([d1f2915](https://github.com/vuejs/core/commit/d1f2915cfe7915fa73624485ff3dd443176a31a9))
+* **compiler-vapor:** handle special characters in cached variable names ([#13626](https://github.com/vuejs/core/issues/13626)) ([a5e106d](https://github.com/vuejs/core/commit/a5e106d96eb17d73c8673e826393c910d5594a2f))
+* **compiler-vapor:** selectors was not initialized in time when the initial value of createFor source was not empty ([#13642](https://github.com/vuejs/core/issues/13642)) ([f04c9c3](https://github.com/vuejs/core/commit/f04c9c342d398c11111c873143dc437f588578ee))
+* **reactivity:** allow collect effects in EffectScope ([#13657](https://github.com/vuejs/core/issues/13657)) ([b9fb79a](https://github.com/vuejs/core/commit/b9fb79a1fd099b67e01c5fe5941551c0da3a0cae)), closes [#13656](https://github.com/vuejs/core/issues/13656)
+* **reactivity:** remove link check to align with 3.5 ([#13654](https://github.com/vuejs/core/issues/13654)) ([3cb27d1](https://github.com/vuejs/core/commit/3cb27d156f6a30e8f950616a53a3726519eaf216)), closes [#13620](https://github.com/vuejs/core/issues/13620)
+* **runtime-core:** use __vapor instead of vapor to identify Vapor components ([#13652](https://github.com/vuejs/core/issues/13652)) ([ad21b1b](https://github.com/vuejs/core/commit/ad21b1b7e96bc894f5df0d95fbd77c9ba6b15c2e))
+* **runtime-vapor:** component emits vdom interop ([#13498](https://github.com/vuejs/core/issues/13498)) ([d95fc18](https://github.com/vuejs/core/commit/d95fc186c26e81345cd75037c3c1304b0eae13b4))
+* **runtime-vapor:** handle v-model vdom interop error ([#13643](https://github.com/vuejs/core/issues/13643)) ([2be828a](https://github.com/vuejs/core/commit/2be828a0c165c7f1533ace0bd81fba43a2af16d6))
+* **runtime-vapor:** remove access globalProperties warning ([#13609](https://github.com/vuejs/core/issues/13609)) ([fca74b0](https://github.com/vuejs/core/commit/fca74b00a86c6039aa05591618539a77aaa72daf))
+
+
+
# [3.6.0-alpha.1](https://github.com/vuejs/core/compare/v3.5.17...v3.6.0-alpha.1) (2025-07-12)
### Features
diff --git a/package.json b/package.json
index d7aa84148..4ecb490a4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"private": true,
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"packageManager": "pnpm@10.12.4",
"type": "module",
"scripts": {
diff --git a/packages/compiler-core/package.json b/packages/compiler-core/package.json
index a42fa8465..e76d747fd 100644
--- a/packages/compiler-core/package.json
+++ b/packages/compiler-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-core",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"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 e65d2b438..3224f5bdb 100644
--- a/packages/compiler-dom/package.json
+++ b/packages/compiler-dom/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-dom",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"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 c77cc27ee..77d4e38b6 100644
--- a/packages/compiler-sfc/package.json
+++ b/packages/compiler-sfc/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-sfc",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"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 fc0ffd2e3..38b08c4f6 100644
--- a/packages/compiler-ssr/package.json
+++ b/packages/compiler-ssr/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-ssr",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"description": "@vue/compiler-ssr",
"main": "dist/compiler-ssr.cjs.js",
"types": "dist/compiler-ssr.d.ts",
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/expression.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/expression.spec.ts.snap
index 7e157236b..fda0121d6 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/expression.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/expression.spec.ts.snap
@@ -11,6 +11,53 @@ export function render(_ctx) {
}"
`;
+exports[`compiler: expression > empty interpolation 1`] = `
+"import { template as _template } from 'vue';
+const t0 = _template(" ")
+
+export function render(_ctx) {
+ const n0 = t0()
+ return n0
+}"
+`;
+
+exports[`compiler: expression > empty interpolation 2`] = `
+"import { template as _template } from 'vue';
+const t0 = _template(" ")
+
+export function render(_ctx) {
+ const n0 = t0()
+ return n0
+}"
+`;
+
+exports[`compiler: expression > empty interpolation 3`] = `
+"import { template as _template } from 'vue';
+const t0 = _template("
", true)
+
+export function render(_ctx) {
+ const n0 = t0()
+ return n0
+}"
+`;
+
+exports[`compiler: expression > empty interpolation 4`] = `
+"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("
", true)
+
+export function render(_ctx) {
+ const n1 = t0()
+ const n0 = _child(n1)
+ const x1 = _child(n1)
+ _renderEffect(() => {
+ const _foo = _ctx.foo
+ _setText(n0, _toDisplayString(_foo))
+ _setText(x1, _toDisplayString(_foo))
+ })
+ return n1
+}"
+`;
+
exports[`compiler: expression > props 1`] = `
"import { toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
const t0 = _template(" ")
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap
index 2d64e1ffe..7184446fc 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap
@@ -43,7 +43,7 @@ export function render(_ctx) {
const n2 = t0()
_setTemplateRef(n2, "foo", void 0, true)
return n2
- }, null, 4)
+ }, undefined, 4)
return n0
}"
`;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
index 141d3e410..69c695a24 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
@@ -93,7 +93,7 @@ export function render(_ctx) {
const x4 = _child(n4)
_renderEffect(() => _setText(x4, _toDisplayString(_for_item1.value+_for_item0.value)))
return n4
- }, null, 1)
+ }, undefined, 1)
return n5
})
return n0
@@ -150,6 +150,7 @@ exports[`compiler: v-for > selector pattern 1`] = `
const t0 = _template("
", true)
export function render(_ctx) {
+ let _selector0_0
const n0 = _createFor(() => (_ctx.rows), (_for_item0) => {
const n2 = t0()
const x2 = _child(n2)
@@ -157,8 +158,9 @@ export function render(_ctx) {
_setText(x2, _toDisplayString(_ctx.selected === _for_item0.value.id ? 'danger' : ''))
})
return n2
- }, (row) => (row.id))
- const _selector0_0 = n0.useSelector(() => _ctx.selected)
+ }, (row) => (row.id), undefined, ({ createSelector }) => {
+ _selector0_0 = createSelector(() => _ctx.selected)
+ })
return n0
}"
`;
@@ -168,14 +170,16 @@ exports[`compiler: v-for > selector pattern 2`] = `
const t0 = _template("
", true)
export function render(_ctx) {
+ let _selector0_0
const n0 = _createFor(() => (_ctx.rows), (_for_item0) => {
const n2 = t0()
_selector0_0(() => {
_setClass(n2, _ctx.selected === _for_item0.value.id ? 'danger' : '')
})
return n2
- }, (row) => (row.id))
- const _selector0_0 = n0.useSelector(() => _ctx.selected)
+ }, (row) => (row.id), undefined, ({ createSelector }) => {
+ _selector0_0 = createSelector(() => _ctx.selected)
+ })
return n0
}"
`;
@@ -202,14 +206,16 @@ exports[`compiler: v-for > selector pattern 4`] = `
const t0 = _template("
", true)
export function render(_ctx) {
+ let _selector0_0
const n0 = _createFor(() => (_ctx.rows), (_for_item0) => {
const n2 = t0()
_selector0_0(() => {
_setClass(n2, { danger: _for_item0.value.id === _ctx.selected })
})
return n2
- }, (row) => (row.id))
- const _selector0_0 = n0.useSelector(() => _ctx.selected)
+ }, (row) => (row.id), undefined, ({ createSelector }) => {
+ _selector0_0 = createSelector(() => _ctx.selected)
+ })
return n0
}"
`;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap
index dd00e5526..e7a2b30e6 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap
@@ -12,6 +12,21 @@ export function render(_ctx) {
}"
`;
+exports[`v-on > component event with special characters 1`] = `
+"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback } from 'vue';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const _on_update_model = () => {}
+ const _on_update_model1 = () => {}
+ const n0 = _createComponentWithFallback(_component_Foo, {
+ "onUpdate:model": () => _on_update_model,
+ "onUpdate-model": () => _on_update_model1
+ }, null, true)
+ return n0
+}"
+`;
+
exports[`v-on > dynamic arg 1`] = `
"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue';
const t0 = _template("", true)
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
index ab3ade45b..b6107d5a1 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
@@ -68,7 +68,7 @@ export function render(_ctx) {
const n0 = _createFor(() => (_ctx.list), (_for_item0) => {
const n2 = t0()
return n2
- }, null, 4)
+ }, undefined, 4)
return n0
}"
`;
diff --git a/packages/compiler-vapor/__tests__/transforms/expression.spec.ts b/packages/compiler-vapor/__tests__/transforms/expression.spec.ts
index 5983bde67..9257a714b 100644
--- a/packages/compiler-vapor/__tests__/transforms/expression.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/expression.spec.ts
@@ -47,4 +47,25 @@ describe('compiler: expression', () => {
expect(code).toMatchSnapshot()
expect(code).contains(`_String(_foo.id++)`)
})
+
+ test('empty interpolation', () => {
+ const { code } = compileWithExpression(`{{}}`)
+ const { code: code2 } = compileWithExpression(`{{ }}`)
+ const { code: code3 } = compileWithExpression(`{{ }}
`)
+ const { code: code4 } = compileWithExpression(`{{ foo }}{{ }}
`)
+
+ expect(code).toMatchSnapshot()
+ expect(code).not.toContain(`_toDisplayString`)
+ expect(code).not.toContain(`_setText`)
+
+ expect(code2).toMatchSnapshot()
+ expect(code2).not.toContain(`_toDisplayString`)
+ expect(code2).not.toContain(`_setText`)
+
+ expect(code3).toMatchSnapshot()
+ expect(code3).not.toContain(`_toDisplayString`)
+ expect(code3).not.toContain(`_setText`)
+
+ expect(code4).toMatchSnapshot()
+ })
})
diff --git a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts
index aca88c791..963f46ad2 100644
--- a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts
@@ -695,4 +695,16 @@ describe('v-on', () => {
expect(code).matchSnapshot()
expect(code).include('n0.$evtclick = e => _ctx.handleClick(e)')
})
+
+ test('component event with special characters', () => {
+ const { code } = compileWithVOn(
+ ` {}" @update-model="() => {}" />`,
+ )
+
+ expect(code).matchSnapshot()
+ expect(code).contains('const _on_update_model = () => {}')
+ expect(code).contains('const _on_update_model1 = () => {}')
+ expect(code).contains('"onUpdate:model": () => _on_update_model')
+ expect(code).contains('"onUpdate-model": () => _on_update_model1')
+ })
})
diff --git a/packages/compiler-vapor/package.json b/packages/compiler-vapor/package.json
index efb667961..81a37cde0 100644
--- a/packages/compiler-vapor/package.json
+++ b/packages/compiler-vapor/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-vapor",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"description": "@vue/compiler-vapor",
"main": "dist/compiler-vapor.cjs.js",
"module": "dist/compiler-vapor.esm-bundler.js",
diff --git a/packages/compiler-vapor/src/generators/component.ts b/packages/compiler-vapor/src/generators/component.ts
index 10705a2c7..fb76abaa5 100644
--- a/packages/compiler-vapor/src/generators/component.ts
+++ b/packages/compiler-vapor/src/generators/component.ts
@@ -26,7 +26,7 @@ import {
genCall,
genMulti,
} from './utils'
-import { genExpression } from './expression'
+import { genExpression, genVarName } from './expression'
import { genPropKey, genPropValue } from './prop'
import {
type SimpleExpressionNode,
@@ -102,6 +102,7 @@ export function genCreateComponent(
function getUniqueHandlerName(context: CodegenContext, name: string): string {
const { seenInlineHandlerNames } = context
+ name = genVarName(name)
const count = seenInlineHandlerNames[name] || 0
seenInlineHandlerNames[name] = count + 1
return count === 0 ? name : `${name}${count}`
diff --git a/packages/compiler-vapor/src/generators/expression.ts b/packages/compiler-vapor/src/generators/expression.ts
index aa7edf658..c70d4a566 100644
--- a/packages/compiler-vapor/src/generators/expression.ts
+++ b/packages/compiler-vapor/src/generators/expression.ts
@@ -647,7 +647,7 @@ function parseExp(context: CodegenContext, content: string): Node {
return parseExpression(`(${content})`, options)
}
-function genVarName(exp: string): string {
+export function genVarName(exp: string): string {
return `${exp
.replace(/[^a-zA-Z0-9]/g, '_')
.replace(/_+/g, '_')
diff --git a/packages/compiler-vapor/src/generators/for.ts b/packages/compiler-vapor/src/generators/for.ts
index 40f002a85..026db797b 100644
--- a/packages/compiler-vapor/src/generators/for.ts
+++ b/packages/compiler-vapor/src/generators/for.ts
@@ -99,19 +99,27 @@ export function genFor(
keyProp,
idMap,
)
- const patternFrag: CodeFragment[] = []
+ const selectorDeclarations: CodeFragment[] = []
+ const selectorSetup: CodeFragment[] = []
for (let i = 0; i < selectorPatterns.length; i++) {
const { selector } = selectorPatterns[i]
const selectorName = `_selector${id}_${i}`
- patternFrag.push(
+ selectorDeclarations.push(`let ${selectorName}`, NEWLINE)
+ if (i === 0) {
+ selectorSetup.push(`({ createSelector }) => {`, INDENT_START)
+ }
+ selectorSetup.push(
NEWLINE,
- `const ${selectorName} = `,
- ...genCall(`n${id}.useSelector`, [
+ `${selectorName} = `,
+ ...genCall(`createSelector`, [
`() => `,
...genExpression(selector, context),
]),
)
+ if (i === selectorPatterns.length - 1) {
+ selectorSetup.push(INDENT_END, NEWLINE, '}')
+ }
}
const blockFn = context.withId(() => {
@@ -165,16 +173,17 @@ export function genFor(
return [
NEWLINE,
+ ...selectorDeclarations,
`const n${id} = `,
...genCall(
- helper('createFor'),
+ [helper('createFor'), 'undefined'],
sourceExpr,
blockFn,
genCallback(keyProp),
flags ? String(flags) : undefined,
+ selectorSetup.length ? selectorSetup : undefined,
// todo: hydrationNode
),
- ...patternFrag,
]
// construct a id -> accessor path map.
diff --git a/packages/compiler-vapor/src/transforms/transformText.ts b/packages/compiler-vapor/src/transforms/transformText.ts
index 5f858058f..e9c273b85 100644
--- a/packages/compiler-vapor/src/transforms/transformText.ts
+++ b/packages/compiler-vapor/src/transforms/transformText.ts
@@ -87,7 +87,8 @@ export const transformText: NodeTransform = (node, context) => {
}
function processInterpolation(context: TransformContext) {
- const children = context.parent!.node.children
+ const parentNode = context.parent!.node
+ const children = parentNode.children
const nexts = children.slice(context.index)
const idx = nexts.findIndex(n => !isTextLike(n))
const nodes = (idx > -1 ? nexts.slice(0, idx) : nexts) as Array
@@ -97,10 +98,18 @@ function processInterpolation(context: TransformContext) {
if (prev && prev.type === NodeTypes.TEXT) {
nodes.unshift(prev)
}
+ const values = processTextLikeChildren(nodes, context)
+
+ if (values.length === 0 && parentNode.type !== NodeTypes.ROOT) {
+ return
+ }
context.template += ' '
const id = context.reference()
- const values = nodes.map(node => createTextLikeExpression(node, context))
+
+ if (values.length === 0) {
+ return
+ }
const nonConstantExps = values.filter(v => !isConstantExpression(v))
const isStatic =
@@ -129,8 +138,10 @@ function processTextContainer(
children: TextLike[],
context: TransformContext,
) {
- const values = children.map(child => createTextLikeExpression(child, context))
+ const values = processTextLikeChildren(children, context)
+
const literals = values.map(getLiteralExpressionValue)
+
if (literals.every(l => l != null)) {
context.childrenTemplate = literals.map(l => String(l))
} else {
@@ -149,13 +160,22 @@ function processTextContainer(
}
}
-function createTextLikeExpression(node: TextLike, context: TransformContext) {
- markNonTemplate(node, context)
- if (node.type === NodeTypes.TEXT) {
- return createSimpleExpression(node.content, true, node.loc)
- } else {
- return node.content as SimpleExpressionNode
+function processTextLikeChildren(nodes: TextLike[], context: TransformContext) {
+ const exps: SimpleExpressionNode[] = []
+ for (const node of nodes) {
+ let exp: SimpleExpressionNode
+ markNonTemplate(node, context)
+
+ if (node.type === NodeTypes.TEXT) {
+ exp = createSimpleExpression(node.content, true, node.loc)
+ } else {
+ exp = node.content as SimpleExpressionNode
+ }
+
+ if (exp.content) exps.push(exp)
}
+
+ return exps
}
function isTextLike(node: TemplateChildNode): node is TextLike {
diff --git a/packages/reactivity/package.json b/packages/reactivity/package.json
index c07f80090..76c9a08b6 100644
--- a/packages/reactivity/package.json
+++ b/packages/reactivity/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/reactivity",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"description": "@vue/reactivity",
"main": "index.js",
"module": "dist/reactivity.esm-bundler.js",
diff --git a/packages/reactivity/src/effectScope.ts b/packages/reactivity/src/effectScope.ts
index 9d8dd546e..36c9b85e8 100644
--- a/packages/reactivity/src/effectScope.ts
+++ b/packages/reactivity/src/effectScope.ts
@@ -1,11 +1,5 @@
import { EffectFlags, cleanup } from './effect'
-import {
- type Link,
- type ReactiveNode,
- link,
- setActiveSub,
- unlink,
-} from './system'
+import { type Link, type ReactiveNode, link, unlink } from './system'
import { warn } from './warning'
export let activeEffectScope: EffectScope | undefined
@@ -65,14 +59,12 @@ export class EffectScope implements ReactiveNode {
}
run(fn: () => T): T | undefined {
- const prevSub = setActiveSub()
const prevScope = activeEffectScope
try {
activeEffectScope = this
return fn()
} finally {
activeEffectScope = prevScope
- setActiveSub(prevSub)
}
}
diff --git a/packages/reactivity/src/system.ts b/packages/reactivity/src/system.ts
index cc3eaad45..93adad335 100644
--- a/packages/reactivity/src/system.ts
+++ b/packages/reactivity/src/system.ts
@@ -77,14 +77,8 @@ export function link(dep: ReactiveNode, sub: ReactiveNode): void {
return
}
}
+ // TODO: maybe can find a good way to check duplicate link
const prevSub = dep.subsTail
- if (
- prevSub !== undefined &&
- prevSub.sub === sub &&
- (!recursedCheck || isValidLink(prevSub, sub))
- ) {
- return
- }
const newLink =
(sub.depsTail =
dep.subsTail =
diff --git a/packages/runtime-core/package.json b/packages/runtime-core/package.json
index 527869ae7..d379ef7f4 100644
--- a/packages/runtime-core/package.json
+++ b/packages/runtime-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/runtime-core",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"description": "@vue/runtime-core",
"main": "index.js",
"module": "dist/runtime-core.esm-bundler.js",
diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts
index 6483e2241..eab407cb5 100644
--- a/packages/runtime-core/src/hmr.ts
+++ b/packages/runtime-core/src/hmr.ts
@@ -119,7 +119,7 @@ function reload(id: string, newComp: HMRComponent): void {
// create a snapshot which avoids the set being mutated during updates
const instances = [...record.instances]
- if (newComp.vapor) {
+ if (newComp.__vapor) {
for (const instance of instances) {
instance.hmrReload!(newComp)
}
diff --git a/packages/runtime-dom/package.json b/packages/runtime-dom/package.json
index 934499370..36fb787fa 100644
--- a/packages/runtime-dom/package.json
+++ b/packages/runtime-dom/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/runtime-dom",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"description": "@vue/runtime-dom",
"main": "index.js",
"module": "dist/runtime-dom.esm-bundler.js",
diff --git a/packages/runtime-vapor/__tests__/apiCreateSelector.spec.ts b/packages/runtime-vapor/__tests__/apiCreateSelector.spec.ts
index 9b36a2c31..9a3745fb5 100644
--- a/packages/runtime-vapor/__tests__/apiCreateSelector.spec.ts
+++ b/packages/runtime-vapor/__tests__/apiCreateSelector.spec.ts
@@ -1,12 +1,11 @@
import { ref } from '@vue/reactivity'
import { makeRender } from './_utils'
-// @ts-expect-error
-import { createFor, createSelector, renderEffect } from '../src'
+import { createFor } from '../src'
import { nextTick } from '@vue/runtime-dom'
const define = makeRender()
-describe.todo('api: createSelector', () => {
+describe('api: createSelector', () => {
test('basic', async () => {
let calledTimes = 0
let expectedCalledTimes = 0
@@ -15,19 +14,23 @@ describe.todo('api: createSelector', () => {
const index = ref(0)
const { host } = define(() => {
- const isSleected = createSelector(index)
+ let selector: (cb: () => void) => void
return createFor(
() => list.value,
item => {
const span = document.createElement('li')
- renderEffect(() => {
+ selector(() => {
calledTimes += 1
const { id } = item.value
- span.textContent = `${id}.${isSleected(id) ? 't' : 'f'}`
+ span.textContent = `${id}.${id === index.value ? 't' : 'f'}`
})
return span
},
item => item.id,
+ undefined,
+ ({ createSelector }) => {
+ selector = createSelector(() => index.value)
+ },
)
}).render()
@@ -50,66 +53,11 @@ describe.todo('api: createSelector', () => {
)
expect(calledTimes).toBe((expectedCalledTimes += 2))
- list.value[2].id = 3
- await nextTick()
- expect(host.innerHTML).toBe(
- '0.f1.f3.f',
- )
- expect(calledTimes).toBe((expectedCalledTimes += 1))
- })
-
- test('custom compare', async () => {
- let calledTimes = 0
- let expectedCalledTimes = 0
-
- const list = ref([{ id: 1 }, { id: 2 }, { id: 3 }])
- const index = ref(0)
-
- const { host } = define(() => {
- const isSleected = createSelector(
- index,
- // @ts-expect-error
- (key, value) => key === value + 1,
- )
- return createFor(
- () => list.value,
- item => {
- const span = document.createElement('li')
- renderEffect(() => {
- calledTimes += 1
- const { id } = item.value
- span.textContent = `${id}.${isSleected(id) ? 't' : 'f'}`
- })
- return span
- },
- item => item.id,
- )
- }).render()
-
- expect(host.innerHTML).toBe(
- '1.t2.f3.f',
- )
- expect(calledTimes).toBe((expectedCalledTimes += 3))
-
- index.value = 1
- await nextTick()
- expect(host.innerHTML).toBe(
- '1.f2.t3.f',
- )
- expect(calledTimes).toBe((expectedCalledTimes += 2))
-
- index.value = 2
- await nextTick()
- expect(host.innerHTML).toBe(
- '1.f2.f3.t',
- )
- expect(calledTimes).toBe((expectedCalledTimes += 2))
-
- list.value[2].id = 4
- await nextTick()
- expect(host.innerHTML).toBe(
- '1.f2.f4.f',
- )
- expect(calledTimes).toBe((expectedCalledTimes += 1))
+ // list.value[2].id = 3
+ // await nextTick()
+ // expect(host.innerHTML).toBe(
+ // '0.f1.f3.f',
+ // )
+ // expect(calledTimes).toBe((expectedCalledTimes += 1))
})
})
diff --git a/packages/runtime-vapor/__tests__/apiCreateVaporApp.spec.ts b/packages/runtime-vapor/__tests__/apiCreateVaporApp.spec.ts
index c82d432f1..6b21e5e55 100644
--- a/packages/runtime-vapor/__tests__/apiCreateVaporApp.spec.ts
+++ b/packages/runtime-vapor/__tests__/apiCreateVaporApp.spec.ts
@@ -341,7 +341,7 @@ describe('api: createVaporApp', () => {
})
})
- test('config.globalProperty', () => {
+ test.todo('config.globalProperty', () => {
const { app } = define({
setup() {
return []
@@ -351,7 +351,7 @@ describe('api: createVaporApp', () => {
app.config.globalProperties.msg = 'hello world'
} catch (e) {}
expect(
- `app.config.globalProperties is not supported in vapor mode`,
+ `app.config.globalProperties is not supported in vapor mode components`,
).toHaveBeenWarned()
})
})
diff --git a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts
index 96222e6ee..98c4cdbc9 100644
--- a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts
+++ b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts
@@ -1,6 +1,23 @@
-import { createVNode, defineComponent, h, renderSlot } from '@vue/runtime-dom'
+import {
+ createVNode,
+ defineComponent,
+ h,
+ nextTick,
+ ref,
+ renderSlot,
+ toDisplayString,
+ useModel,
+} from '@vue/runtime-dom'
import { makeInteropRender } from './_utils'
-import { createComponent, defineVaporComponent } from '../src'
+import {
+ applyTextModel,
+ child,
+ createComponent,
+ defineVaporComponent,
+ renderEffect,
+ setText,
+ template,
+} from '../src'
const define = makeInteropRender()
@@ -26,6 +43,54 @@ describe('vdomInterop', () => {
})
})
+ describe('v-model', () => {
+ test('basic work', async () => {
+ const VaporChild = defineVaporComponent({
+ props: {
+ modelValue: {},
+ modelModifiers: {},
+ },
+ emits: ['update:modelValue'],
+ setup(__props) {
+ const modelValue = useModel(__props, 'modelValue')
+
+ const n0 = template('
')() as any
+ const n1 = template('')() as any
+ const x0 = child(n0) as any
+ applyTextModel(
+ n1,
+ () => modelValue.value,
+ _value => (modelValue.value = _value),
+ )
+ renderEffect(() => setText(x0, toDisplayString(modelValue.value)))
+ return [n0, n1]
+ },
+ })
+
+ const { html, host } = define({
+ setup() {
+ const msg = ref('foo')
+ return () =>
+ h(VaporChild as any, {
+ modelValue: msg.value,
+ 'onUpdate:modelValue': (value: string) => {
+ msg.value = value
+ },
+ })
+ },
+ }).render()
+
+ expect(html()).toBe('foo
')
+
+ const inputEl = host.querySelector('input')!
+ inputEl.value = 'bar'
+ inputEl.dispatchEvent(new Event('input'))
+
+ await nextTick()
+ expect(html()).toBe('bar
')
+ })
+ })
+
describe('emit', () => {
test('emit from vapor child to vdom parent', () => {
const VaporChild = defineVaporComponent({
diff --git a/packages/runtime-vapor/package.json b/packages/runtime-vapor/package.json
index 9a61a3cd3..f27ef46b7 100644
--- a/packages/runtime-vapor/package.json
+++ b/packages/runtime-vapor/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/runtime-vapor",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"description": "@vue/runtime-vapor",
"main": "index.js",
"module": "dist/runtime-vapor.esm-bundler.js",
diff --git a/packages/runtime-vapor/src/apiCreateApp.ts b/packages/runtime-vapor/src/apiCreateApp.ts
index ee4c00c88..bcc680eae 100644
--- a/packages/runtime-vapor/src/apiCreateApp.ts
+++ b/packages/runtime-vapor/src/apiCreateApp.ts
@@ -88,18 +88,6 @@ function prepareApp() {
}
function postPrepareApp(app: App) {
- if (__DEV__) {
- app.config.globalProperties = new Proxy(
- {},
- {
- set() {
- warn(`app.config.globalProperties is not supported in vapor mode.`)
- return false
- },
- },
- )
- }
-
app.vapor = true
const mount = app.mount
app.mount = (container, ...args: any[]) => {
diff --git a/packages/runtime-vapor/src/apiCreateFor.ts b/packages/runtime-vapor/src/apiCreateFor.ts
index 426a5c56b..9ffdf6dca 100644
--- a/packages/runtime-vapor/src/apiCreateFor.ts
+++ b/packages/runtime-vapor/src/apiCreateFor.ts
@@ -74,6 +74,9 @@ export const createFor = (
) => Block,
getKey?: (item: any, key: any, index?: number) => any,
flags = 0,
+ setup?: (_: {
+ createSelector: (source: () => any) => (cb: () => void) => void
+ }) => void,
): VaporFragment => {
const _insertionParent = insertionParent
const _insertionAnchor = insertionAnchor
@@ -402,6 +405,10 @@ export const createFor = (
}
}
+ if (setup) {
+ setup({ createSelector })
+ }
+
if (flags & VaporVForFlags.ONCE) {
renderList()
} else {
@@ -412,12 +419,9 @@ export const createFor = (
insert(frag, _insertionParent, _insertionAnchor)
}
- // @ts-expect-error
- frag.useSelector = useSelector
-
return frag
- function useSelector(source: () => any): (key: any, cb: () => void) => void {
+ function createSelector(source: () => any): (cb: () => void) => void {
let operMap = new Map void)[]>()
let activeKey = source()
let activeOpers: (() => void)[] | undefined
diff --git a/packages/server-renderer/package.json b/packages/server-renderer/package.json
index 039414ca8..cb4da84e4 100644
--- a/packages/server-renderer/package.json
+++ b/packages/server-renderer/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/server-renderer",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"description": "@vue/server-renderer",
"main": "index.js",
"module": "dist/server-renderer.esm-bundler.js",
diff --git a/packages/shared/package.json b/packages/shared/package.json
index 13656d505..b4703addd 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/shared",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"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 e02f068ff..cd2917e6b 100644
--- a/packages/vue-compat/package.json
+++ b/packages/vue-compat/package.json
@@ -1,6 +1,6 @@
{
"name": "@vue/compat",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"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 6b3069db0..ab734ee7a 100644
--- a/packages/vue/package.json
+++ b/packages/vue/package.json
@@ -1,6 +1,6 @@
{
"name": "vue",
- "version": "3.6.0-alpha.1",
+ "version": "3.6.0-alpha.2",
"description": "The progressive JavaScript framework for building modern web UI.",
"main": "index.js",
"module": "dist/vue.runtime.esm-bundler.js",