@@ -39,132 +39,132 @@ import { PatchFlags, PatchFlagNames } from '@vue/shared'
39
39
export const transformFor = createStructuralDirectiveTransform (
40
40
'for' ,
41
41
( node , dir , context ) => {
42
- if ( dir . exp ) {
43
- const parseResult = parseForExpression (
44
- // can only be simple expression because vFor transform is applied
45
- // before expression transform.
46
- dir . exp as SimpleExpressionNode ,
47
- context
42
+ if ( ! dir . exp ) {
43
+ context . onError (
44
+ createCompilerError ( ErrorCodes . X_V_FOR_NO_EXPRESSION , dir . loc )
48
45
)
46
+ return
47
+ }
49
48
50
- if ( parseResult ) {
51
- const { helper, addIdentifiers, removeIdentifiers, scopes } = context
52
- const { source, value, key, index } = parseResult
49
+ const parseResult = parseForExpression (
50
+ // can only be simple expression because vFor transform is applied
51
+ // before expression transform.
52
+ dir . exp as SimpleExpressionNode ,
53
+ context
54
+ )
53
55
54
- // create the loop render function expression now, and add the
55
- // iterator on exit after all children have been traversed
56
- const renderExp = createCallExpression ( helper ( RENDER_LIST ) , [ source ] )
57
- const keyProp = findProp ( node , `key` )
58
- const fragmentFlag = keyProp
59
- ? PatchFlags . KEYED_FRAGMENT
60
- : PatchFlags . UNKEYED_FRAGMENT
61
- const codegenNode = createSequenceExpression ( [
62
- createCallExpression ( helper ( OPEN_BLOCK ) ) ,
63
- createCallExpression ( helper ( CREATE_BLOCK ) , [
64
- helper ( FRAGMENT ) ,
65
- `null` ,
66
- renderExp ,
67
- fragmentFlag +
68
- ( __DEV__ ? ` /* ${ PatchFlagNames [ fragmentFlag ] } */` : `` )
69
- ] )
70
- ] ) as ForCodegenNode
56
+ if ( ! parseResult ) {
57
+ context . onError (
58
+ createCompilerError ( ErrorCodes . X_V_FOR_MALFORMED_EXPRESSION , dir . loc )
59
+ )
60
+ return
61
+ }
71
62
72
- context . replaceNode ( {
73
- type : NodeTypes . FOR ,
74
- loc : dir . loc ,
75
- source,
76
- valueAlias : value ,
77
- keyAlias : key ,
78
- objectIndexAlias : index ,
79
- children :
80
- node . tagType === ElementTypes . TEMPLATE ? node . children : [ node ] ,
81
- codegenNode
82
- } )
63
+ const { helper, addIdentifiers, removeIdentifiers, scopes } = context
64
+ const { source, value, key, index } = parseResult
83
65
84
- // bookkeeping
85
- scopes . vFor ++
86
- if ( ! __BROWSER__ && context . prefixIdentifiers ) {
87
- // scope management
88
- // inject identifiers to context
89
- value && addIdentifiers ( value )
90
- key && addIdentifiers ( key )
91
- index && addIdentifiers ( index )
92
- }
66
+ // create the loop render function expression now, and add the
67
+ // iterator on exit after all children have been traversed
68
+ const renderExp = createCallExpression ( helper ( RENDER_LIST ) , [ source ] )
69
+ const keyProp = findProp ( node , `key` )
70
+ const fragmentFlag = keyProp
71
+ ? PatchFlags . KEYED_FRAGMENT
72
+ : PatchFlags . UNKEYED_FRAGMENT
73
+ const codegenNode = createSequenceExpression ( [
74
+ createCallExpression ( helper ( OPEN_BLOCK ) ) ,
75
+ createCallExpression ( helper ( CREATE_BLOCK ) , [
76
+ helper ( FRAGMENT ) ,
77
+ `null` ,
78
+ renderExp ,
79
+ fragmentFlag + ( __DEV__ ? ` /* ${ PatchFlagNames [ fragmentFlag ] } */` : `` )
80
+ ] )
81
+ ] ) as ForCodegenNode
82
+
83
+ context . replaceNode ( {
84
+ type : NodeTypes . FOR ,
85
+ loc : dir . loc ,
86
+ source,
87
+ valueAlias : value ,
88
+ keyAlias : key ,
89
+ objectIndexAlias : index ,
90
+ children : node . tagType === ElementTypes . TEMPLATE ? node . children : [ node ] ,
91
+ codegenNode
92
+ } )
93
93
94
- return ( ) => {
95
- scopes . vFor --
96
- if ( ! __BROWSER__ && context . prefixIdentifiers ) {
97
- value && removeIdentifiers ( value )
98
- key && removeIdentifiers ( key )
99
- index && removeIdentifiers ( index )
100
- }
94
+ // bookkeeping
95
+ scopes . vFor ++
96
+ if ( ! __BROWSER__ && context . prefixIdentifiers ) {
97
+ // scope management
98
+ // inject identifiers to context
99
+ value && addIdentifiers ( value )
100
+ key && addIdentifiers ( key )
101
+ index && addIdentifiers ( index )
102
+ }
101
103
102
- // finish the codegen now that all children have been traversed
103
- let childBlock
104
- const isTemplate = isTemplateNode ( node )
105
- const slotOutlet = isSlotOutlet ( node )
106
- ? node
107
- : isTemplate &&
108
- node . children . length === 1 &&
109
- isSlotOutlet ( node . children [ 0 ] )
110
- ? node . children [ 0 ]
111
- : null
112
- const keyProperty = keyProp
113
- ? createObjectProperty (
114
- `key` ,
115
- keyProp . type === NodeTypes . ATTRIBUTE
116
- ? createSimpleExpression ( keyProp . value ! . content , true )
117
- : keyProp . exp !
118
- )
119
- : null
120
- if ( slotOutlet ) {
121
- // <slot v-for="..."> or <template v-for="..."><slot/></template>
122
- childBlock = slotOutlet . codegenNode !
123
- if ( isTemplate && keyProperty ) {
124
- // <template v-for="..." :key="..."><slot/></template>
125
- // we need to inject the key to the renderSlot() call.
126
- // the props for renderSlot is passed as the 3rd argument.
127
- injectProp ( childBlock , keyProperty , context )
128
- }
129
- } else if ( isTemplate ) {
130
- // <template v-for="...">
131
- // should generate a fragment block for each loop
132
- childBlock = createBlockExpression (
133
- createCallExpression ( helper ( CREATE_BLOCK ) , [
134
- helper ( FRAGMENT ) ,
135
- keyProperty ? createObjectExpression ( [ keyProperty ] ) : `null` ,
136
- node . children
137
- ] ) ,
138
- context
139
- )
140
- } else {
141
- // Normal element v-for. Directly use the child's codegenNode
142
- // arguments, but replace createVNode() with createBlock()
143
- let codegenNode = node . codegenNode as ElementCodegenNode
144
- if ( codegenNode . callee === APPLY_DIRECTIVES ) {
145
- codegenNode . arguments [ 0 ] . callee = helper ( CREATE_BLOCK )
146
- } else {
147
- codegenNode . callee = helper ( CREATE_BLOCK )
148
- }
149
- childBlock = createBlockExpression ( codegenNode , context )
150
- }
104
+ return ( ) => {
105
+ scopes . vFor --
106
+ if ( ! __BROWSER__ && context . prefixIdentifiers ) {
107
+ value && removeIdentifiers ( value )
108
+ key && removeIdentifiers ( key )
109
+ index && removeIdentifiers ( index )
110
+ }
151
111
152
- renderExp . arguments . push (
153
- createFunctionExpression (
154
- createForLoopParams ( parseResult ) ,
155
- childBlock ,
156
- true /* force newline */
157
- )
112
+ // finish the codegen now that all children have been traversed
113
+ let childBlock
114
+ const isTemplate = isTemplateNode ( node )
115
+ const slotOutlet = isSlotOutlet ( node )
116
+ ? node
117
+ : isTemplate &&
118
+ node . children . length === 1 &&
119
+ isSlotOutlet ( node . children [ 0 ] )
120
+ ? node . children [ 0 ]
121
+ : null
122
+ const keyProperty = keyProp
123
+ ? createObjectProperty (
124
+ `key` ,
125
+ keyProp . type === NodeTypes . ATTRIBUTE
126
+ ? createSimpleExpression ( keyProp . value ! . content , true )
127
+ : keyProp . exp !
158
128
)
129
+ : null
130
+ if ( slotOutlet ) {
131
+ // <slot v-for="..."> or <template v-for="..."><slot/></template>
132
+ childBlock = slotOutlet . codegenNode !
133
+ if ( isTemplate && keyProperty ) {
134
+ // <template v-for="..." :key="..."><slot/></template>
135
+ // we need to inject the key to the renderSlot() call.
136
+ // the props for renderSlot is passed as the 3rd argument.
137
+ injectProp ( childBlock , keyProperty , context )
159
138
}
160
- } else {
161
- context . onError (
162
- createCompilerError ( ErrorCodes . X_V_FOR_MALFORMED_EXPRESSION , dir . loc )
139
+ } else if ( isTemplate ) {
140
+ // <template v-for="...">
141
+ // should generate a fragment block for each loop
142
+ childBlock = createBlockExpression (
143
+ createCallExpression ( helper ( CREATE_BLOCK ) , [
144
+ helper ( FRAGMENT ) ,
145
+ keyProperty ? createObjectExpression ( [ keyProperty ] ) : `null` ,
146
+ node . children
147
+ ] ) ,
148
+ context
163
149
)
150
+ } else {
151
+ // Normal element v-for. Directly use the child's codegenNode
152
+ // arguments, but replace createVNode() with createBlock()
153
+ let codegenNode = node . codegenNode as ElementCodegenNode
154
+ if ( codegenNode . callee === APPLY_DIRECTIVES ) {
155
+ codegenNode . arguments [ 0 ] . callee = helper ( CREATE_BLOCK )
156
+ } else {
157
+ codegenNode . callee = helper ( CREATE_BLOCK )
158
+ }
159
+ childBlock = createBlockExpression ( codegenNode , context )
164
160
}
165
- } else {
166
- context . onError (
167
- createCompilerError ( ErrorCodes . X_V_FOR_NO_EXPRESSION , dir . loc )
161
+
162
+ renderExp . arguments . push (
163
+ createFunctionExpression (
164
+ createForLoopParams ( parseResult ) ,
165
+ childBlock ,
166
+ true /* force newline */
167
+ )
168
168
)
169
169
}
170
170
}
0 commit comments