Skip to content

Commit

Permalink
fix(compiler-core): bail out to array children when the element has c…
Browse files Browse the repository at this point in the history
…ustom directives + only one text child node (#3757)
  • Loading branch information
HcySunYang authored May 12, 2021
1 parent 0e3bbd0 commit a56ab14
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,24 @@ return function render(_ctx, _cache) {
}"
`;
exports[`compiler: transform text element with custom directives and only one text child node 1`] = `
"const _Vue = Vue
return function render(_ctx, _cache) {
with (_ctx) {
const { toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, resolveDirective: _resolveDirective, withDirectives: _withDirectives, openBlock: _openBlock, createBlock: _createBlock } = _Vue
const _directive_foo = _resolveDirective(\\"foo\\")
return _withDirectives((_openBlock(), _createBlock(\\"p\\", null, [
_createTextVNode(_toDisplayString(foo), 1 /* TEXT */)
], 512 /* NEED_PATCH */)), [
[_directive_foo]
])
}
}"
`;
exports[`compiler: transform text no consecutive text 1`] = `
"const _Vue = Vue
Expand Down
32 changes: 29 additions & 3 deletions packages/compiler-core/__tests__/transforms/transformText.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
transform,
NodeTypes,
generate,
ForNode
ForNode,
ElementNode
} from '../../src'
import { transformFor } from '../../src/transforms/vFor'
import { transformText } from '../../src/transforms/transformText'
Expand All @@ -20,8 +21,8 @@ function transformWithTextOpt(template: string, options: CompilerOptions = {}) {
nodeTransforms: [
transformFor,
...(options.prefixIdentifiers ? [transformExpression] : []),
transformText,
transformElement
transformElement,
transformText
],
...options
})
Expand Down Expand Up @@ -193,4 +194,29 @@ describe('compiler: transform text', () => {
}).code
).toMatchSnapshot()
})

// #3756
test('element with custom directives and only one text child node', () => {
const root = transformWithTextOpt(`<p v-foo>{{ foo }}</p>`)
expect(root.children.length).toBe(1)
expect(root.children[0].type).toBe(NodeTypes.ELEMENT)
expect((root.children[0] as ElementNode).children[0]).toMatchObject({
type: NodeTypes.TEXT_CALL,
codegenNode: {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_TEXT,
arguments: [
{
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'foo'
}
},
genFlagText(PatchFlags.TEXT)
]
}
})
expect(generate(root).code).toMatchSnapshot()
})
})
10 changes: 10 additions & 0 deletions packages/compiler-core/src/transforms/transformText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ export const transformText: NodeTransform = (node, context) => {
(node.type === NodeTypes.ROOT ||
(node.type === NodeTypes.ELEMENT &&
node.tagType === ElementTypes.ELEMENT &&
// #3756
// custom directives can potentially add DOM elements arbitrarily,
// we need to avoid setting textContent of the element at runtime
// to avoid accidentally overwriting the DOM elements added
// by the user through custom directives.
!node.props.find(
p =>
p.type === NodeTypes.DIRECTIVE &&
!context.directiveTransforms[p.name]
) &&
// in compat mode, <template> tags with no special directives
// will be rendered as a fragment so its children must be
// converted into vnodes.
Expand Down

0 comments on commit a56ab14

Please sign in to comment.