vuejs/core

v-text directive does not work after SSR if another custom directive is applied to the same element

mefcorvi opened this issue · 1 comments

Vue version

Introduced in 3.4.36. Works fine in 3.4.35.

Link to minimal reproduction

https://play.vuejs.org/#__SSR__eNp9kU9LAzEQxb/KmEsV2l1KxUPZFlQK1YOKCl4CUrbT3dRsEpLZtVD2uzvZpX8O0kAOmfeS+b3MXtw7lzQ1iqnIQu6VIwhItZtLoypnPcEePG6ghY23FQzYOpBGmtyaQFCFAmZRvx4sUWsLX9br9dXg5mRplqooNW9i516aVpos7TtxDz4QVk6vCPkEkJVjaEbl8UozItzRTAruJMU8S8tx71PG1VGu7Br1QYeUxSw9e1EMBQUG2agi2QZrOCYzAEiR28opjf7VkWJQKaaRDnhJseIov89djXyNw0M9LzH/+ae+DbtYk+LNY0DfoBRHjVa+QOrlxccLpzkTmb7W7L4gvmOwuo6Mve2hNmvGPvN1tE/dsJQpPsNiR2jCIVQEjc6280vBA3y8EP2EO0luu3s8Mv7F7wZ9fJM/kIVkcifaPxRnvOg=

Steps to reproduce

  1. Define a custom directive, even an empty one without any handlers.
  2. In the page template, create a div with both v-text and the custom directive applied.
  3. Open the page in SSR mode.

What is expected?

The text set by the v-text directive is displayed.

What is actually happening?

The text does not appear. No errors are logged.

System Info

No response

Any additional comments?

If SSR mode is disabled, everything works as expected. v-html directive works fine in both modes.

Related to 79602f9 #8112

Currently, in the case with the custom directive, this branch is triggered, adding an entry to rawChildrenMap:

} else if (directives.length && !node.children.length) {
const tempId = `_temp${context.temps++}`
propsExp.arguments = [
createAssignmentExpression(
createSimpleExpression(tempId, false),
mergedProps,
),
]
rawChildrenMap.set(
node,
createConditionalExpression(
createSimpleExpression(`"textContent" in ${tempId}`, false),
createCallExpression(context.helper(SSR_INTERPOLATE), [
createSimpleExpression(`${tempId}.textContent`, false),
]),
createSimpleExpression(`${tempId}.innerHTML ?? ''`, false),
false,
),
)
}

The v-html directive works correctly because it overrides the entry in rawChildrenMap, whereas v-text only updates the children property of the node.

if (prop.name === 'html' && prop.exp) {
rawChildrenMap.set(
node,
createCompoundExpression([`(`, prop.exp, `) ?? ''`]),
)
} else if (prop.name === 'text' && prop.exp) {
node.children = [createInterpolation(prop.exp, prop.loc)]
} else if (prop.name === 'slot') {