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 7739fcb0c..3d1368b74 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
@@ -1,18 +1,15 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: v-for > array de-structured value 1`] = `
-"import { renderEffect as _renderEffect, setText as _setText, createFor as _createFor, template as _template } from 'vue/vapor';
+"import { renderEffect as _renderEffect, setText as _setText, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("
")
export function render(_ctx) {
- const n0 = _createFor(() => (_ctx.list), (_ctx0) => {
+ const n0 = _createFor(() => (_ctx.list), _withDestructure((_state, [[id, ...other], index] = _state) => [id, other, index], (_ctx0) => {
const n2 = t0()
_renderEffect(() => _setText(n2, _ctx0[0] + _ctx0[1] + _ctx0[2]))
return n2
- }, ([id, ...other], index) => (id), null, null, false, _state => {
- const [[id, ...other], index] = _state
- return [id, other, index]
- })
+ }), ([id, ...other], index) => (id))
return n0
}"
`;
@@ -69,35 +66,29 @@ export function render(_ctx) {
`;
exports[`compiler: v-for > object de-structured value 1`] = `
-"import { renderEffect as _renderEffect, setText as _setText, createFor as _createFor, template as _template } from 'vue/vapor';
+"import { renderEffect as _renderEffect, setText as _setText, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("")
export function render(_ctx) {
- const n0 = _createFor(() => (_ctx.list), (_ctx0) => {
+ const n0 = _createFor(() => (_ctx.list), _withDestructure((_state, [{ id, ...other }, index] = _state) => [id, other, index], (_ctx0) => {
const n2 = t0()
_renderEffect(() => _setText(n2, _ctx0[0] + _ctx0[1] + _ctx0[2]))
return n2
- }, ({ id, ...other }, index) => (id), null, null, false, _state => {
- const [{ id, ...other }, index] = _state
- return [id, other, index]
- })
+ }), ({ id, ...other }, index) => (id))
return n0
}"
`;
exports[`compiler: v-for > v-for aliases w/ complex expressions 1`] = `
-"import { renderEffect as _renderEffect, setText as _setText, createFor as _createFor, template as _template } from 'vue/vapor';
+"import { renderEffect as _renderEffect, setText as _setText, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("")
export function render(_ctx) {
- const n0 = _createFor(() => (_ctx.list), (_ctx0) => {
+ const n0 = _createFor(() => (_ctx.list), _withDestructure((_state, [{ foo = bar, baz: [qux = quux] }] = _state) => [foo, qux], (_ctx0) => {
const n2 = t0()
_renderEffect(() => _setText(n2, _ctx0[0] + _ctx.bar + _ctx.baz + _ctx0[1] + _ctx.quux))
return n2
- }, null, null, null, false, _state => {
- const [{ foo = bar, baz: [qux = quux] }] = _state
- return [foo, qux]
- })
+ }))
return n0
}"
`;
diff --git a/packages/compiler-vapor/__tests__/transforms/vFor.spec.ts b/packages/compiler-vapor/__tests__/transforms/vFor.spec.ts
index f457ac745..f3fa72a47 100644
--- a/packages/compiler-vapor/__tests__/transforms/vFor.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/vFor.spec.ts
@@ -129,7 +129,9 @@ describe('compiler: v-for', () => {
`{{ id + other + index }}
`,
)
expect(code).matchSnapshot()
- expect(code).contains(`return [id, other, index]`)
+ expect(code).contains(
+ `(_state, [{ id, ...other }, index] = _state) => [id, other, index]`,
+ )
expect(code).contains(`_ctx0[0] + _ctx0[1] + _ctx0[2]`)
expect(ir.block.operation[0]).toMatchObject({
type: IRNodeTypes.FOR,
@@ -162,7 +164,9 @@ describe('compiler: v-for', () => {
`{{ id + other + index }}
`,
)
expect(code).matchSnapshot()
- expect(code).contains(`return [id, other, index]`)
+ expect(code).contains(
+ `(_state, [[id, ...other], index] = _state) => [id, other, index]`,
+ )
expect(code).contains(`_ctx0[0] + _ctx0[1] + _ctx0[2]`)
expect(ir.block.operation[0]).toMatchObject({
type: IRNodeTypes.FOR,
@@ -197,7 +201,9 @@ describe('compiler: v-for', () => {
`,
)
expect(code).matchSnapshot()
- expect(code).contains(`return [foo, qux]`)
+ expect(code).contains(
+ `(_state, [{ foo = bar, baz: [qux = quux] }] = _state) => [foo, qux]`,
+ )
expect(code).contains(
`_ctx0[0] + _ctx.bar + _ctx.baz + _ctx0[1] + _ctx.quux`,
)
diff --git a/packages/compiler-vapor/src/generators/for.ts b/packages/compiler-vapor/src/generators/for.ts
index 9c3b962f9..c8d74342c 100644
--- a/packages/compiler-vapor/src/generators/for.ts
+++ b/packages/compiler-vapor/src/generators/for.ts
@@ -6,8 +6,6 @@ import type { ForIRNode } from '../ir'
import {
type CodeFragment,
DELIMITERS_ARRAY,
- INDENT_END,
- INDENT_START,
NEWLINE,
genCall,
genMulti,
@@ -51,7 +49,7 @@ export function genFor(
if (rawKey) idMap[rawKey] = `${propsName}[${idsOfValue.size}]`
if (rawIndex) idMap[rawIndex] = `${propsName}[${idsOfValue.size + 1}]`
- const blockFn = context.withId(
+ let blockFn = context.withId(
() => genBlock(render, context, [propsName]),
idMap,
)
@@ -77,31 +75,28 @@ export function genFor(
]
}
- let destructureAssignmentFn: CodeFragment[] | false = false
if (isDestructureAssignment) {
const idMap: Record = {}
idsOfValue.forEach(id => (idMap[id] = null))
if (rawKey) idMap[rawKey] = null
if (rawIndex) idMap[rawIndex] = null
- destructureAssignmentFn = [
- '_state => {',
- INDENT_START,
- NEWLINE,
- 'const ',
+ const destructureAssignmentFn: CodeFragment[] = [
+ '(_state, ',
...genMulti(
DELIMITERS_ARRAY,
rawValue ? rawValue : rawKey || rawIndex ? '_' : undefined,
rawKey ? rawKey : rawIndex ? '__' : undefined,
rawIndex,
),
- ' = _state',
- NEWLINE,
- 'return ',
+ ' = _state) => ',
...genMulti(DELIMITERS_ARRAY, ...idsOfValue, rawKey, rawIndex),
- INDENT_END,
- NEWLINE,
- '}',
]
+
+ blockFn = genCall(
+ vaporHelper('withDestructure'),
+ destructureAssignmentFn,
+ blockFn,
+ )
}
return [
@@ -114,8 +109,7 @@ export function genFor(
getKeyFn,
false, // todo: getMemo
false, // todo: hydrationNode
- (once && 'true') || (destructureAssignmentFn && 'false'),
- destructureAssignmentFn,
+ once && 'true',
),
]
}
diff --git a/packages/runtime-vapor/__tests__/for.spec.ts b/packages/runtime-vapor/__tests__/for.spec.ts
index 2d028d069..c1d981cb2 100644
--- a/packages/runtime-vapor/__tests__/for.spec.ts
+++ b/packages/runtime-vapor/__tests__/for.spec.ts
@@ -7,6 +7,7 @@ import {
renderEffect,
shallowRef,
template,
+ withDestructure,
withDirectives,
} from '../src'
import { makeRender } from './_utils'
@@ -318,25 +319,24 @@ describe('createFor', () => {
const { host } = define(() => {
const n1 = createFor(
() => list.value,
- state => {
- const span = document.createElement('li')
- renderEffect(() => {
- const [name, key, index] = state
- span.innerHTML = `${key}. ${name}`
-
- // index should be undefined if source is not an object
- expect(index).toBe(undefined)
- })
- return span
- },
+ withDestructure(
+ state => {
+ const [{ name }, key, index] = state
+ return [name, key, index]
+ },
+ state => {
+ const span = document.createElement('li')
+ renderEffect(() => {
+ const [name, key, index] = state
+ span.innerHTML = `${key}. ${name}`
+
+ // index should be undefined if source is not an object
+ expect(index).toBe(undefined)
+ })
+ return span
+ },
+ ),
item => item.name,
- undefined,
- undefined,
- false,
- state => {
- const [{ name }, key, index] = state
- return [name, key, index]
- },
)
return n1
}).render()
diff --git a/packages/runtime-vapor/src/apiCreateFor.ts b/packages/runtime-vapor/src/apiCreateFor.ts
index 446141700..07bbd151f 100644
--- a/packages/runtime-vapor/src/apiCreateFor.ts
+++ b/packages/runtime-vapor/src/apiCreateFor.ts
@@ -26,7 +26,6 @@ import {
invokeWithUpdate,
} from './directivesChildFragment'
import type { DynamicSlot } from './componentSlots'
-import { destructuring } from './destructuring'
interface ForBlock extends Fragment {
scope: BlockEffectScope
@@ -49,7 +48,6 @@ export const createFor = (
getMemo?: (item: any, key: any, index?: number) => any[],
hydrationNode?: Node,
once?: boolean,
- assignment?: (state: any[]) => any[],
): Fragment => {
let isMounted = false
let oldBlocks: ForBlock[] = []
@@ -283,11 +281,7 @@ export const createFor = (
memo: getMemo && getMemo(item, key, index),
[fragmentKey]: true,
})
- const proxyState = proxyRefs(state)
- const itemCtx = assignment
- ? destructuring(scope, proxyState, assignment)
- : proxyState
- block.nodes = scope.run(() => renderItem(itemCtx))!
+ block.nodes = scope.run(() => renderItem(proxyRefs(state)))!
invokeWithMount(scope, () => {
// TODO v-memo
diff --git a/packages/runtime-vapor/src/destructure.ts b/packages/runtime-vapor/src/destructure.ts
new file mode 100644
index 000000000..20030dd32
--- /dev/null
+++ b/packages/runtime-vapor/src/destructure.ts
@@ -0,0 +1,19 @@
+import { shallowReactive } from '@vue/reactivity'
+import { renderEffect } from './renderEffect'
+
+export function withDestructure(
+ assign: (...args: P) => any[],
+ block: (ctx: any[]) => R,
+): (...args: P) => R {
+ return (...args: P) => {
+ const ctx = shallowReactive([])
+ renderEffect(() => {
+ const res = assign(...args)
+ const len = res.length
+ for (let i = 0; i < len; i++) {
+ ctx[i] = res[i]
+ }
+ })
+ return block(ctx)
+ }
+}
diff --git a/packages/runtime-vapor/src/destructuring.ts b/packages/runtime-vapor/src/destructuring.ts
deleted file mode 100644
index 255130dac..000000000
--- a/packages/runtime-vapor/src/destructuring.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { type EffectScope, shallowReactive } from '@vue/reactivity'
-import { renderEffect } from './renderEffect'
-
-export function destructuring(
- scope: EffectScope,
- state: any,
- fn: (state: any) => any[],
-) {
- const list = shallowReactive([])
- scope.run(() => {
- renderEffect(() => {
- const res = fn(state)
- const len = res.length
- for (let i = 0; i < len; i++) {
- list[i] = res[i]
- }
- })
- })
- return list
-}
diff --git a/packages/runtime-vapor/src/index.ts b/packages/runtime-vapor/src/index.ts
index 79a0b26a6..60810713e 100644
--- a/packages/runtime-vapor/src/index.ts
+++ b/packages/runtime-vapor/src/index.ts
@@ -135,6 +135,8 @@ export { createComponent } from './apiCreateComponent'
export { resolveComponent, resolveDirective } from './helpers/resolveAssets'
export { toHandlers } from './helpers/toHandlers'
+export { withDestructure } from './destructure'
+
// **Internal** DOM-only runtime directive helpers
export {
vModelText,