@@ -15,6 +15,7 @@ import type {
15
15
TransformContext ,
16
16
} from '../transform'
17
17
import {
18
+ DynamicFlag ,
18
19
IRNodeTypes ,
19
20
type IRProp ,
20
21
type IRProps ,
@@ -29,8 +30,7 @@ export const isReservedProp = /*#__PURE__*/ makeMap(
29
30
30
31
export const transformElement : NodeTransform = ( node , context ) => {
31
32
return function postTransformElement ( ) {
32
- node = context . node
33
-
33
+ ; ( { node } = context )
34
34
if (
35
35
! (
36
36
node . type === NodeTypes . ELEMENT &&
@@ -41,37 +41,94 @@ export const transformElement: NodeTransform = (node, context) => {
41
41
return
42
42
}
43
43
44
- const { tag, props } = node
45
- const isComponent = node . tagType === ElementTypes . COMPONENT
44
+ const { tag, tagType } = node
45
+ const isComponent = tagType === ElementTypes . COMPONENT
46
+ const propsResult = buildProps (
47
+ node ,
48
+ context as TransformContext < ElementNode > ,
49
+ )
50
+
51
+ ; ( isComponent ? transformComponentElement : transformNativeElement ) (
52
+ tag ,
53
+ propsResult ,
54
+ context ,
55
+ )
56
+ }
57
+ }
46
58
47
- context . template += `<${ tag } `
48
- if ( props . length ) {
49
- buildProps (
50
- node ,
51
- context as TransformContext < ElementNode > ,
52
- undefined ,
53
- isComponent ,
54
- )
55
- }
56
- const { scopeId } = context . options
57
- if ( scopeId ) {
58
- context . template += ` ${ scopeId } `
59
- }
60
- context . template += `>` + context . childrenTemplate . join ( '' )
59
+ function transformComponentElement (
60
+ tag : string ,
61
+ propsResult : PropsResult ,
62
+ context : TransformContext ,
63
+ ) {
64
+ const { bindingMetadata } = context . options
65
+ const resolve = ! bindingMetadata [ tag ]
66
+ context . dynamic . flags |= DynamicFlag . NON_TEMPLATE | DynamicFlag . INSERT
67
+
68
+ context . registerOperation ( {
69
+ type : IRNodeTypes . CREATE_COMPONENT_NODE ,
70
+ id : context . reference ( ) ,
71
+ tag,
72
+ props : propsResult [ 0 ] ? propsResult [ 1 ] : [ propsResult [ 1 ] ] ,
73
+ resolve,
74
+ } )
75
+ }
61
76
62
- // TODO remove unnecessary close tag, e.g. if it's the last element of the template
63
- if ( ! isVoidTag ( tag ) ) {
64
- context . template += `</${ tag } >`
77
+ function transformNativeElement (
78
+ tag : string ,
79
+ propsResult : ReturnType < typeof buildProps > ,
80
+ context : TransformContext ,
81
+ ) {
82
+ const { scopeId } = context . options
83
+
84
+ context . template += `<${ tag } `
85
+ if ( scopeId ) context . template += ` ${ scopeId } `
86
+
87
+ if ( propsResult [ 0 ] /* dynamic props */ ) {
88
+ const [ , dynamicArgs , expressions ] = propsResult
89
+ context . registerEffect ( expressions , [
90
+ {
91
+ type : IRNodeTypes . SET_DYNAMIC_PROPS ,
92
+ element : context . reference ( ) ,
93
+ props : dynamicArgs ,
94
+ } ,
95
+ ] )
96
+ } else {
97
+ for ( const prop of propsResult [ 1 ] ) {
98
+ const { key, values } = prop
99
+ if ( key . isStatic && values . length === 1 && values [ 0 ] . isStatic ) {
100
+ context . template += ` ${ key . content } `
101
+ if ( values [ 0 ] . content ) context . template += `="${ values [ 0 ] . content } "`
102
+ } else {
103
+ context . registerEffect ( values , [
104
+ {
105
+ type : IRNodeTypes . SET_PROP ,
106
+ element : context . reference ( ) ,
107
+ prop,
108
+ } ,
109
+ ] )
110
+ }
65
111
}
66
112
}
113
+
114
+ context . template += `>` + context . childrenTemplate . join ( '' )
115
+ // TODO remove unnecessary close tag, e.g. if it's the last element of the template
116
+ if ( ! isVoidTag ( tag ) ) {
117
+ context . template += `</${ tag } >`
118
+ }
67
119
}
68
120
121
+ export type PropsResult =
122
+ | [ dynamic : true , props : IRProps [ ] , expressions : SimpleExpressionNode [ ] ]
123
+ | [ dynamic : false , props : IRProp [ ] ]
124
+
69
125
function buildProps (
70
126
node : ElementNode ,
71
127
context : TransformContext < ElementNode > ,
72
- props : ( VaporDirectiveNode | AttributeNode ) [ ] = node . props as any ,
73
- isComponent : boolean ,
74
- ) {
128
+ ) : PropsResult {
129
+ const props = node . props as ( VaporDirectiveNode | AttributeNode ) [ ]
130
+ if ( props . length === 0 ) return [ false , [ ] ]
131
+
75
132
const dynamicArgs : IRProps [ ] = [ ]
76
133
const dynamicExpr : SimpleExpressionNode [ ] = [ ]
77
134
let results : DirectiveTransformResult [ ] = [ ]
@@ -112,31 +169,11 @@ function buildProps(
112
169
if ( dynamicArgs . length || results . some ( ( { key } ) => ! key . isStatic ) ) {
113
170
// take rest of props as dynamic props
114
171
pushMergeArg ( )
115
- context . registerEffect ( dynamicExpr , [
116
- {
117
- type : IRNodeTypes . SET_DYNAMIC_PROPS ,
118
- element : context . reference ( ) ,
119
- props : dynamicArgs ,
120
- } ,
121
- ] )
122
- } else {
123
- const irProps = dedupeProperties ( results )
124
- for ( const prop of irProps ) {
125
- const { key, values } = prop
126
- if ( key . isStatic && values . length === 1 && values [ 0 ] . isStatic ) {
127
- context . template += ` ${ key . content } `
128
- if ( values [ 0 ] . content ) context . template += `="${ values [ 0 ] . content } "`
129
- } else {
130
- context . registerEffect ( values , [
131
- {
132
- type : IRNodeTypes . SET_PROP ,
133
- element : context . reference ( ) ,
134
- prop,
135
- } ,
136
- ] )
137
- }
138
- }
172
+ return [ true , dynamicArgs , dynamicExpr ]
139
173
}
174
+
175
+ const irProps = dedupeProperties ( results )
176
+ return [ false , irProps ]
140
177
}
141
178
142
179
function transformProp (
0 commit comments