Repository: vuejs/vue-next
File: packages/compiler-vapor/src/transforms/transformText.ts (TypeScript)

Code before:
    nonConstantExps.every(e =>
      isStaticExpression(e, context.options.bindingMetadata),
    ) ||
    context.inVOnce

  if (isStatic) {
    context.registerOperation({
      type: IRNodeTypes.SET_TEXT,
      element: id,
      values,
    })
  } else {
    context.registerEffect(values, {
      type: IRNodeTypes.SET_TEXT,
      element: id,
      values,
    })
  }
}

function processTextContainer(
  children: TextLike[],
  context: TransformContext<ElementNode>,
) {
  const values = children
    .map(child => createTextLikeExpression(child, context))
    .filter(v =>
      v.type === NodeTypes.SIMPLE_EXPRESSION ? v.content.length !== 0 : true,
    )

  const literals = values.map(getLiteralExpressionValue)

  if (literals.every(l => l != null)) {
    context.childrenTemplate = literals.map(l => String(l))
  } else {
    context.childrenTemplate = [' ']
    context.registerOperation({
      type: IRNodeTypes.GET_TEXT_CHILD,
      parent: context.reference(),
    })
    context.registerEffect(values, {
      type: IRNodeTypes.SET_TEXT,
      element: context.reference(),
      values,
      // indicates this node is generated, so prefix should be "x" instead of "n"
      generated: true,
    })
  }
}

function createTextLikeExpression(node: TextLike, context: TransformContext) {

Review comment (refactor):
This logic is duplicated with the code above (line 103). Perhaps we can extract a function that also incorporates the logic of `createTextLikeExpression`.

- logic reusability
- only traverse the children once

```ts
function processTextLikeChildren(children:TextLike[]){
  const exps:SimpleExpressionNode[]=[]
  for(node ... children){
    markNonTemplate(node, context)
    // skip empty node
    if(!node.content) continue

    if (node.type === NodeTypes.TEXT) {
      exps.push(...)
    } else {
      exps.push(...)
    }
  }

  return exps
}
```


Code after:
  if (isStatic) {
    context.registerOperation({
      type: IRNodeTypes.SET_TEXT,
      element: id,
      values,
    })
  } else {
    context.registerEffect(values, {
      type: IRNodeTypes.SET_TEXT,
      element: id,
      values,
    })
  }
}

function processTextContainer(
  children: TextLike[],
  context: TransformContext<ElementNode>,
) {
  const values = processTextLikeChildren(children, context)

  const literals = values.map(getLiteralExpressionValue)

  if (literals.every(l => l != null)) {
    context.childrenTemplate = literals.map(l => String(l))
  } else {
    context.childrenTemplate = [' ']
    context.registerOperation({
      type: IRNodeTypes.GET_TEXT_CHILD,
      parent: context.reference(),
    })
    context.registerEffect(values, {
      type: IRNodeTypes.SET_TEXT,
      element: context.reference(),
      values,
      // indicates this node is generated, so prefix should be "x" instead of "n"
      generated: true,
    })
  }
}

function processTextLikeChildren(nodes: TextLike[], context: TransformContext) {
  const exps: SimpleExpressionNode[] = []
  for (const node of nodes) {
    let exp: SimpleExpressionNode
    markNonTemplate(node, context)

    if (node.type === NodeTypes.TEXT) {
      exp = createSimpleExpression(node.content, true, node.loc)
    } else {
      exp = node.content as SimpleExpressionNode