fix(compiler-dom): properly stringify v-html/v-text with constant value
fix #5439 close #5445
This commit is contained in:
parent
cd92654510
commit
6283b2ec41
@ -59,6 +59,7 @@ export {
|
|||||||
PropsExpression
|
PropsExpression
|
||||||
} from './transforms/transformElement'
|
} from './transforms/transformElement'
|
||||||
export { processSlotOutlet } from './transforms/transformSlotOutlet'
|
export { processSlotOutlet } from './transforms/transformSlotOutlet'
|
||||||
|
export { getConstantType } from './transforms/hoistStatic'
|
||||||
export { generateCodeFrame } from '@vue/shared'
|
export { generateCodeFrame } from '@vue/shared'
|
||||||
|
|
||||||
// v2 compat only
|
// v2 compat only
|
||||||
|
@ -32,3 +32,23 @@ return function render(_ctx, _cache) {
|
|||||||
return (_openBlock(), _createElementBlock(\\"div\\", null, _hoisted_2))
|
return (_openBlock(), _createElementBlock(\\"div\\", null, _hoisted_2))
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`stringify static html stringify v-html 1`] = `
|
||||||
|
"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode } = Vue
|
||||||
|
|
||||||
|
const _hoisted_1 = /*#__PURE__*/_createStaticVNode(\\"<pre data-type=\\\\\\"js\\\\\\"><code><span>show-it </span></code></pre><div class><span class>1</span><span class>2</span></div>\\", 2)
|
||||||
|
|
||||||
|
return function render(_ctx, _cache) {
|
||||||
|
return _hoisted_1
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`stringify static html stringify v-text 1`] = `
|
||||||
|
"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode } = Vue
|
||||||
|
|
||||||
|
const _hoisted_1 = /*#__PURE__*/_createStaticVNode(\\"<pre data-type=\\\\\\"js\\\\\\"><code><span>show-it </span></code></pre><div class><span class>1</span><span class>2</span></div>\\", 2)
|
||||||
|
|
||||||
|
return function render(_ctx, _cache) {
|
||||||
|
return _hoisted_1
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
@ -433,4 +433,25 @@ describe('stringify static html', () => {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #5439
|
||||||
|
test('stringify v-html', () => {
|
||||||
|
const { code } = compileWithStringify(`
|
||||||
|
<pre data-type="js"><code v-html="'<span>show-it </span>'"></code></pre>
|
||||||
|
<div class>
|
||||||
|
<span class>1</span><span class>2</span>
|
||||||
|
</div>`)
|
||||||
|
expect(code).toMatch(`<code><span>show-it </span></code>`)
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('stringify v-text', () => {
|
||||||
|
const { code } = compileWithStringify(`
|
||||||
|
<pre data-type="js"><code v-text="'<span>show-it </span>'"></code></pre>
|
||||||
|
<div class>
|
||||||
|
<span class>1</span><span class>2</span>
|
||||||
|
</div>`)
|
||||||
|
expect(code).toMatch(`<code><span>show-it </span></code>`)
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -279,6 +279,7 @@ function stringifyElement(
|
|||||||
context: TransformContext
|
context: TransformContext
|
||||||
): string {
|
): string {
|
||||||
let res = `<${node.tag}`
|
let res = `<${node.tag}`
|
||||||
|
let innerHTML = ''
|
||||||
for (let i = 0; i < node.props.length; i++) {
|
for (let i = 0; i < node.props.length; i++) {
|
||||||
const p = node.props[i]
|
const p = node.props[i]
|
||||||
if (p.type === NodeTypes.ATTRIBUTE) {
|
if (p.type === NodeTypes.ATTRIBUTE) {
|
||||||
@ -286,28 +287,38 @@ function stringifyElement(
|
|||||||
if (p.value) {
|
if (p.value) {
|
||||||
res += `="${escapeHtml(p.value.content)}"`
|
res += `="${escapeHtml(p.value.content)}"`
|
||||||
}
|
}
|
||||||
} else if (p.type === NodeTypes.DIRECTIVE && p.name === 'bind') {
|
} else if (p.type === NodeTypes.DIRECTIVE) {
|
||||||
const exp = p.exp as SimpleExpressionNode
|
if (p.name === 'bind') {
|
||||||
if (exp.content[0] === '_') {
|
const exp = p.exp as SimpleExpressionNode
|
||||||
// internally generated string constant references
|
if (exp.content[0] === '_') {
|
||||||
// e.g. imported URL strings via compiler-sfc transformAssetUrl plugin
|
// internally generated string constant references
|
||||||
res += ` ${(p.arg as SimpleExpressionNode).content}="__VUE_EXP_START__${
|
// e.g. imported URL strings via compiler-sfc transformAssetUrl plugin
|
||||||
exp.content
|
res += ` ${
|
||||||
}__VUE_EXP_END__"`
|
(p.arg as SimpleExpressionNode).content
|
||||||
continue
|
}="__VUE_EXP_START__${exp.content}__VUE_EXP_END__"`
|
||||||
}
|
continue
|
||||||
// constant v-bind, e.g. :foo="1"
|
|
||||||
let evaluated = evaluateConstant(exp)
|
|
||||||
if (evaluated != null) {
|
|
||||||
const arg = p.arg && (p.arg as SimpleExpressionNode).content
|
|
||||||
if (arg === 'class') {
|
|
||||||
evaluated = normalizeClass(evaluated)
|
|
||||||
} else if (arg === 'style') {
|
|
||||||
evaluated = stringifyStyle(normalizeStyle(evaluated))
|
|
||||||
}
|
}
|
||||||
res += ` ${(p.arg as SimpleExpressionNode).content}="${escapeHtml(
|
// constant v-bind, e.g. :foo="1"
|
||||||
evaluated
|
let evaluated = evaluateConstant(exp)
|
||||||
)}"`
|
if (evaluated != null) {
|
||||||
|
const arg = p.arg && (p.arg as SimpleExpressionNode).content
|
||||||
|
if (arg === 'class') {
|
||||||
|
evaluated = normalizeClass(evaluated)
|
||||||
|
} else if (arg === 'style') {
|
||||||
|
evaluated = stringifyStyle(normalizeStyle(evaluated))
|
||||||
|
}
|
||||||
|
res += ` ${(p.arg as SimpleExpressionNode).content}="${escapeHtml(
|
||||||
|
evaluated
|
||||||
|
)}"`
|
||||||
|
}
|
||||||
|
} else if (p.name === 'html') {
|
||||||
|
// #5439 v-html with constant value
|
||||||
|
// not sure why would anyone do this but it can happen
|
||||||
|
innerHTML = evaluateConstant(p.exp as SimpleExpressionNode)
|
||||||
|
} else if (p.name === 'text') {
|
||||||
|
innerHTML = escapeHtml(
|
||||||
|
toDisplayString(evaluateConstant(p.exp as SimpleExpressionNode))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,8 +326,12 @@ function stringifyElement(
|
|||||||
res += ` ${context.scopeId}`
|
res += ` ${context.scopeId}`
|
||||||
}
|
}
|
||||||
res += `>`
|
res += `>`
|
||||||
for (let i = 0; i < node.children.length; i++) {
|
if (innerHTML) {
|
||||||
res += stringifyNode(node.children[i], context)
|
res += innerHTML
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < node.children.length; i++) {
|
||||||
|
res += stringifyNode(node.children[i], context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!isVoidTag(node.tag)) {
|
if (!isVoidTag(node.tag)) {
|
||||||
res += `</${node.tag}>`
|
res += `</${node.tag}>`
|
||||||
|
@ -3,7 +3,8 @@ import {
|
|||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
TO_DISPLAY_STRING,
|
TO_DISPLAY_STRING,
|
||||||
createCallExpression
|
createCallExpression,
|
||||||
|
getConstantType
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
||||||
|
|
||||||
@ -25,11 +26,13 @@ export const transformVText: DirectiveTransform = (dir, node, context) => {
|
|||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
createSimpleExpression(`textContent`, true),
|
createSimpleExpression(`textContent`, true),
|
||||||
exp
|
exp
|
||||||
? createCallExpression(
|
? getConstantType(exp, context) > 0
|
||||||
context.helperString(TO_DISPLAY_STRING),
|
? exp
|
||||||
[exp],
|
: createCallExpression(
|
||||||
loc
|
context.helperString(TO_DISPLAY_STRING),
|
||||||
)
|
[exp],
|
||||||
|
loc
|
||||||
|
)
|
||||||
: createSimpleExpression('', true)
|
: createSimpleExpression('', true)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user