import { createObjectExpression , ConstantTypes , createVNodeCall } from '../ast' ; import { NodeTypes , PatchFlags } from '../../shared/svu' ; import { isStaticExp } from '../../shared' ; import { getConstantType } from './hoistStatic' ; export const transformElement = ( node , context ) => { if ( ! ( node . type === NodeTypes . ELEMENT ) ) { return ; } return function postTransformElement ( ) { const { tag , props } = node ; const vnodeTag = `"${ tag }"` ; let vnodeProps ; let vnodeChildren ; let vnodePatchFlag ; let patchFlag = 0 ; let vnodeDynamicProps ; let dynamicPropNames ; let shouldUseBlock ; if ( props . length > 0 ) { const propsBuildResult = buildProps ( node , context ) ; vnodeProps = propsBuildResult . props ; patchFlag = propsBuildResult . patchFlag ; dynamicPropNames = propsBuildResult . dynamicPropNames ; } if ( node . children . length > 0 ) { if ( node . children . length === 1 ) { const child = node . children [ 0 ] ; const type = child . type ; const hasDynamicTextChild = type === NodeTypes . INTERPOLATION || type === NodeTypes . COMPOUND_EXPRESSION ; if ( hasDynamicTextChild && getConstantType ( child , context ) === ConstantTypes . NOT_CONSTANT ) { patchFlag |= PatchFlags . TEXT ; } if ( hasDynamicTextChild || type === NodeTypes . TEXT ) { vnodeChildren = child ; } else { vnodeChildren = node . children ; } } else { vnodeChildren = node . children ; } } if ( patchFlag !== 0 ) { vnodePatchFlag = String ( patchFlag ) ; if ( dynamicPropNames && dynamicPropNames . length ) { vnodeDynamicProps = stringifyDynamicPropNames ( dynamicPropNames ) ; } } node . codegenNode = createVNodeCall ( context , vnodeTag , vnodeProps , vnodeChildren , vnodePatchFlag , vnodeDynamicProps , ! ! shouldUseBlock , false , node . loc ) ; } ; } ; export function buildProps ( node , context , props = node . props ) { const { loc : elementLoc } = node ; let properties = [ ] ; let patchFlag = 0 ; const dynamicPropNames = [ ] ; const analyzePatchFlag = ( { key } ) => { if ( isStaticExp ( key ) ) { const name = key . content ; if ( name !== 'key' && ! dynamicPropNames . includes ( name ) ) { dynamicPropNames . push ( name ) ; } } } ; for ( let i = 0 ; i < props . length ; i ++ ) { const prop = props [ i ] ; const { name } = prop ; const directiveTransform = context . directiveTransforms [ name ] ; if ( directiveTransform ) { const { props } = directiveTransform ( prop , node , context ) ; props . forEach ( analyzePatchFlag ) ; properties . push ( ... props ) ; } } let propsExpression = undefined ; if ( properties . length ) { propsExpression = createObjectExpression ( properties , elementLoc ) ; } if ( dynamicPropNames . length ) { patchFlag |= PatchFlags . PROPS ; } return { props : propsExpression , patchFlag , dynamicPropNames } ; } function stringifyDynamicPropNames ( props ) { let propsNamesString = `[` ; for ( let i = 0 , l = props . length ; i < l ; i ++ ) { propsNamesString += JSON . stringify ( props [ i ] ) ; if ( i < l - 1 ) propsNamesString += ', ' ; } return propsNamesString + `]` ; }