1- import { walkIdentifiers } from '@vue/compiler-dom'
1+ import { type SimpleExpressionNode , walkIdentifiers } from '@vue/compiler-dom'
22import { genBlock } from './block'
33import { genExpression } from './expression'
44import type { CodegenContext } from '../generate'
@@ -16,75 +16,21 @@ export function genFor(
1616 context : CodegenContext ,
1717) : CodeFragment [ ] {
1818 const { vaporHelper } = context
19- const { source, value, key, index, render, keyProp, once, id } = oper
19+ const { source, value, key, index, render, keyProp, once, id, memo } = oper
2020
2121 let isDestructureAssignment = false
2222 let rawValue : string | null = null
2323 const rawKey = key && key . content
2424 const rawIndex = index && index . content
2525
2626 const sourceExpr = [ '() => (' , ...genExpression ( source , context ) , ')' ]
27-
28- const idsOfValue = new Set < string > ( )
29- if ( value ) {
30- rawValue = value && value . content
31- if ( ( isDestructureAssignment = ! ! value . ast ) ) {
32- walkIdentifiers (
33- value . ast ,
34- ( id , _ , __ , ___ , isLocal ) => {
35- if ( isLocal ) idsOfValue . add ( id . name )
36- } ,
37- true ,
38- )
39- } else {
40- idsOfValue . add ( rawValue )
41- }
42- }
43-
44- const [ depth , exitScope ] = context . enterScope ( )
45- let propsName : string
46- const idMap : Record < string , string | null > = { }
47- if ( context . options . prefixIdentifiers ) {
48- propsName = `_ctx${ depth } `
49- Array . from ( idsOfValue ) . forEach (
50- ( id , idIndex ) => ( idMap [ id ] = `${ propsName } [${ idIndex } ].value` ) ,
51- )
52- if ( rawKey ) idMap [ rawKey ] = `${ propsName } [${ idsOfValue . size } ].value`
53- if ( rawIndex ) idMap [ rawIndex ] = `${ propsName } [${ idsOfValue . size + 1 } ].value`
54- } else {
55- propsName = `[${ [ rawValue || ( ( rawKey || rawIndex ) && '_' ) , rawKey || ( rawIndex && '__' ) , rawIndex ] . filter ( Boolean ) . join ( ', ' ) } ]`
56- }
57-
58- let blockFn = context . withId (
59- ( ) => genBlock ( render , context , [ propsName ] ) ,
60- idMap ,
61- )
62- exitScope ( )
63-
64- let getKeyFn : CodeFragment [ ] | false = false
65- if ( keyProp ) {
66- const idMap : Record < string , null > = { }
67- if ( rawKey ) idMap [ rawKey ] = null
68- if ( rawIndex ) idMap [ rawIndex ] = null
69- idsOfValue . forEach ( id => ( idMap [ id ] = null ) )
70-
71- const expr = context . withId ( ( ) => genExpression ( keyProp , context ) , idMap )
72- getKeyFn = [
73- ...genMulti (
74- [ '(' , ')' , ', ' ] ,
75- rawValue ? rawValue : rawKey || rawIndex ? '_' : undefined ,
76- rawKey ? rawKey : rawIndex ? '__' : undefined ,
77- rawIndex ,
78- ) ,
79- ' => (' ,
80- ...expr ,
81- ')' ,
82- ]
83- }
27+ const idsInValue = getIdsInValue ( )
28+ let blockFn = genBlockFn ( )
29+ const simpleIdMap : Record < string , null > = genSimpleIdMap ( )
8430
8531 if ( isDestructureAssignment ) {
8632 const idMap : Record < string , null > = { }
87- idsOfValue . forEach ( id => ( idMap [ id ] = null ) )
33+ idsInValue . forEach ( id => ( idMap [ id ] = null ) )
8834 if ( rawKey ) idMap [ rawKey ] = null
8935 if ( rawIndex ) idMap [ rawIndex ] = null
9036 const destructureAssignmentFn : CodeFragment [ ] = [
@@ -96,7 +42,7 @@ export function genFor(
9642 rawIndex ,
9743 ) ,
9844 ') => ' ,
99- ...genMulti ( DELIMITERS_ARRAY , ...idsOfValue , rawKey , rawIndex ) ,
45+ ...genMulti ( DELIMITERS_ARRAY , ...idsInValue , rawKey , rawIndex ) ,
10046 ]
10147
10248 blockFn = genCall (
@@ -113,10 +59,77 @@ export function genFor(
11359 vaporHelper ( 'createFor' ) ,
11460 sourceExpr ,
11561 blockFn ,
116- getKeyFn ,
117- false , // todo: getMemo
62+ genCallback ( keyProp ) ,
63+ genCallback ( memo ) ,
11864 false , // todo: hydrationNode
11965 once && 'true' ,
12066 ) ,
12167 ]
68+
69+ function getIdsInValue ( ) {
70+ const idsInValue = new Set < string > ( )
71+ if ( value ) {
72+ rawValue = value && value . content
73+ if ( ( isDestructureAssignment = ! ! value . ast ) ) {
74+ walkIdentifiers (
75+ value . ast ,
76+ ( id , _ , __ , ___ , isLocal ) => {
77+ if ( isLocal ) idsInValue . add ( id . name )
78+ } ,
79+ true ,
80+ )
81+ } else {
82+ idsInValue . add ( rawValue )
83+ }
84+ }
85+ return idsInValue
86+ }
87+
88+ function genBlockFn ( ) {
89+ const [ depth , exitScope ] = context . enterScope ( )
90+ let propsName : string
91+ const idMap : Record < string , string | null > = { }
92+ if ( context . options . prefixIdentifiers ) {
93+ propsName = `_ctx${ depth } `
94+ Array . from ( idsInValue ) . forEach (
95+ ( id , idIndex ) => ( idMap [ id ] = `${ propsName } [${ idIndex } ].value` ) ,
96+ )
97+ if ( rawKey ) idMap [ rawKey ] = `${ propsName } [${ idsInValue . size } ].value`
98+ if ( rawIndex )
99+ idMap [ rawIndex ] = `${ propsName } [${ idsInValue . size + 1 } ].value`
100+ } else {
101+ propsName = `[${ [ rawValue || ( ( rawKey || rawIndex ) && '_' ) , rawKey || ( rawIndex && '__' ) , rawIndex ] . filter ( Boolean ) . join ( ', ' ) } ]`
102+ }
103+
104+ const blockFn = context . withId (
105+ ( ) => genBlock ( render , context , [ propsName ] ) ,
106+ idMap ,
107+ )
108+ exitScope ( )
109+ return blockFn
110+ }
111+
112+ function genSimpleIdMap ( ) {
113+ const idMap : Record < string , null > = { }
114+ if ( rawKey ) idMap [ rawKey ] = null
115+ if ( rawIndex ) idMap [ rawIndex ] = null
116+ idsInValue . forEach ( id => ( idMap [ id ] = null ) )
117+ return idMap
118+ }
119+
120+ function genCallback ( expr : SimpleExpressionNode | undefined ) {
121+ if ( ! expr ) return false
122+ const res = context . withId ( ( ) => genExpression ( expr , context ) , simpleIdMap )
123+ return [
124+ ...genMulti (
125+ [ '(' , ')' , ', ' ] ,
126+ rawValue ? rawValue : rawKey || rawIndex ? '_' : undefined ,
127+ rawKey ? rawKey : rawIndex ? '__' : undefined ,
128+ rawIndex ,
129+ ) ,
130+ ' => (' ,
131+ ...res ,
132+ ')' ,
133+ ]
134+ }
122135}
0 commit comments