Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
test('TEXT', () => {
const { node } = parseWithBind(`<div>foo</div>`)
expect(node.arguments.length).toBe(3)
const { node: node2 } = parseWithBind(`<div>{{ foo }}</div>`)
expect(node2.arguments.length).toBe(4)
expect(node2.arguments[3]).toBe(genFlagText(PatchFlags.TEXT))
// multiple nodes, merged with optimize text
const { node: node3 } = parseWithBind(`<div>foo {{ bar }} baz</div>`)
expect(node3.arguments.length).toBe(4)
expect(node3.arguments[3]).toBe(genFlagText(PatchFlags.TEXT))
})
test('TEXT', () => {
const { node } = parseWithBind(`<div>foo</div>`)
expect(node.arguments.length).toBe(3)
const { node: node2 } = parseWithBind(`<div>{{ foo }}</div>`)
expect(node2.arguments.length).toBe(4)
expect(node2.arguments[3]).toBe(genFlagText(PatchFlags.TEXT))
// multiple nodes, merged with optimize text
const { node: node3 } = parseWithBind(`<div>foo {{ bar }} baz</div>`)
expect(node3.arguments.length).toBe(4)
expect(node3.arguments[3]).toBe(genFlagText(PatchFlags.TEXT))
})
}
if (isComponent) {
const { slots, hasDynamicSlots } = buildSlots(node, context)
args.push(slots)
if (hasDynamicSlots) {
patchFlag |= PatchFlags.DYNAMIC_SLOTS
}
} else if (node.children.length === 1) {
const child = node.children[0]
const type = child.type
// check for dynamic text children
const hasDynamicTextChild =
type === NodeTypes.INTERPOLATION ||
type === NodeTypes.COMPOUND_EXPRESSION
if (hasDynamicTextChild && !isStaticNode(child)) {
patchFlag |= PatchFlags.TEXT
}
// pass directly if the only child is a text node
// (plain / interpolation / expression)
if (hasDynamicTextChild || type === NodeTypes.TEXT) {
args.push(child)
} else {
args.push(node.children)
}
} else {
args.push(node.children)
}
}
// patchFlag & dynamicPropNames
if (patchFlag !== 0) {
if (!hasChildren) {
if (!hasProps) {
// pre-convert text nodes into createTextVNode(text) calls to avoid
// runtime normalization.
for (let i = 0; i < children.length; i++) {
const child = children[i]
if (isText(child) || child.type === NodeTypes.COMPOUND_EXPRESSION) {
const callArgs: CallExpression['arguments'] = []
// createTextVNode defaults to single whitespace, so if it is a
// single space the code could be an empty call to save bytes.
if (child.type !== NodeTypes.TEXT || child.content !== ' ') {
callArgs.push(child)
}
// mark dynamic text with flag so it gets patched inside a block
if (child.type !== NodeTypes.TEXT) {
callArgs.push(
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
)
}
children[i] = {
type: NodeTypes.TEXT_CALL,
content: child,
loc: child.loc,
codegenNode: createCallExpression(
context.helper(CREATE_TEXT),
callArgs
)
}
}
}
}
}
prev,
isSVG,
n1.children as HostVNode[],
parentComponent,
parentSuspense,
unmountChildren
)
}
}
}
}
// text
// This flag is matched when the element has only dynamic text children.
// this flag is terminal (i.e. skips children diffing).
if (patchFlag & PatchFlags.TEXT) {
if (n1.children !== n2.children) {
hostSetElementText(el, n2.children as string)
}
return // terminal
}
} else if (!optimized && dynamicChildren == null) {
// unoptimized, full diff
patchProps(
el,
n2,
oldProps,
newProps,
parentComponent,
parentSuspense,
isSVG
)
builtInComponentSymbol !== KEEP_ALIVE
) {
const { slots, hasDynamicSlots } = buildSlots(node, context)
args.push(slots)
if (hasDynamicSlots) {
patchFlag |= PatchFlags.DYNAMIC_SLOTS
}
} else if (node.children.length === 1) {
const child = node.children[0]
const type = child.type
// check for dynamic text children
const hasDynamicTextChild =
type === NodeTypes.INTERPOLATION ||
type === NodeTypes.COMPOUND_EXPRESSION
if (hasDynamicTextChild && !isStaticNode(child)) {
patchFlag |= PatchFlags.TEXT
}
// pass directly if the only child is a text node
// (plain / interpolation / expression)
if (hasDynamicTextChild || type === NodeTypes.TEXT) {
args.push(child)
} else {
args.push(node.children)
}
} else {
args.push(node.children)
}
}
// patchFlag & dynamicPropNames
if (patchFlag !== 0) {
if (!hasChildren) {
if (!hasProps) {
child.tagType === ElementTypes.ELEMENT
) {
if (!doNotHoistNode && isStaticNode(child, resultCache)) {
// whole tree is static
child.codegenNode = context.hoist(child.codegenNode!)
continue
} else {
// node may contain dynamic children, but its props may be eligible for
// hoisting.
const codegenNode = child.codegenNode!
if (codegenNode.type === NodeTypes.JS_CALL_EXPRESSION) {
const flag = getPatchFlag(codegenNode)
if (
(!flag ||
flag === PatchFlags.NEED_PATCH ||
flag === PatchFlags.TEXT) &&
!hasDynamicKeyOrRef(child) &&
!hasCachedProps(child)
) {
const props = getNodeProps(child)
if (props && props !== `null`) {
getVNodeCall(codegenNode).arguments[1] = context.hoist(props)
}
}
}
}
}
if (child.type === NodeTypes.ELEMENT) {
walk(child.children, context, resultCache)
} else if (child.type === NodeTypes.FOR) {
// Do not hoist v-for single child because it has to be a block
walk(child.children, context, resultCache, child.children.length === 1)
test('hoist static props for elements with dynamic text children', () => {
const { root, args } = transformWithHoist(
`<div><div id="foo">{{ hello }}</div></div>`
)
expect(root.hoists).toMatchObject([createObjectMatcher({ id: 'foo' })])
expect(args[2]).toMatchObject([
{
type: NodeTypes.ELEMENT,
codegenNode: {
callee: CREATE_VNODE,
arguments: [
`"div"`,
{ content: `_hoisted_1` },
{ type: NodeTypes.INTERPOLATION },
genFlagText(PatchFlags.TEXT)
]
}
}
])
expect(generate(root).code).toMatchSnapshot()
})
type: NodeTypes.TEXT_CALL,
codegenNode: {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_TEXT,
arguments: [
{
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
{ type: NodeTypes.INTERPOLATION, content: { content: `foo` } },
` + `,
{ type: NodeTypes.TEXT, content: ` bar ` },
` + `,
{ type: NodeTypes.INTERPOLATION, content: { content: `baz` } }
]
},
genFlagText(PatchFlags.TEXT)
]
}
})
expect(root.children[2].type).toBe(NodeTypes.ELEMENT)
expect(root.children[3]).toMatchObject({
type: NodeTypes.TEXT_CALL,
codegenNode: {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_TEXT,
arguments: [
{
type: NodeTypes.TEXT,
content: `hello`
}
]
}