1
- import { walkIdentifiers } from '@vue/compiler-dom'
1
+ import { type SimpleExpressionNode , walkIdentifiers } from '@vue/compiler-dom'
2
2
import { genBlock } from './block'
3
3
import { genExpression } from './expression'
4
4
import type { CodegenContext } from '../generate'
@@ -16,75 +16,21 @@ export function genFor(
16
16
context : CodegenContext ,
17
17
) : CodeFragment [ ] {
18
18
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
20
20
21
21
let isDestructureAssignment = false
22
22
let rawValue : string | null = null
23
23
const rawKey = key && key . content
24
24
const rawIndex = index && index . content
25
25
26
26
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 ( )
84
30
85
31
if ( isDestructureAssignment ) {
86
32
const idMap : Record < string , null > = { }
87
- idsOfValue . forEach ( id => ( idMap [ id ] = null ) )
33
+ idsInValue . forEach ( id => ( idMap [ id ] = null ) )
88
34
if ( rawKey ) idMap [ rawKey ] = null
89
35
if ( rawIndex ) idMap [ rawIndex ] = null
90
36
const destructureAssignmentFn : CodeFragment [ ] = [
@@ -96,7 +42,7 @@ export function genFor(
96
42
rawIndex ,
97
43
) ,
98
44
') => ' ,
99
- ...genMulti ( DELIMITERS_ARRAY , ...idsOfValue , rawKey , rawIndex ) ,
45
+ ...genMulti ( DELIMITERS_ARRAY , ...idsInValue , rawKey , rawIndex ) ,
100
46
]
101
47
102
48
blockFn = genCall (
@@ -113,10 +59,77 @@ export function genFor(
113
59
vaporHelper ( 'createFor' ) ,
114
60
sourceExpr ,
115
61
blockFn ,
116
- getKeyFn ,
117
- false , // todo: getMemo
62
+ genCallback ( keyProp ) ,
63
+ genCallback ( memo ) ,
118
64
false , // todo: hydrationNode
119
65
once && 'true' ,
120
66
) ,
121
67
]
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
+ }
122
135
}
0 commit comments