fix(compiler-core): known global should be shadowed by local variables in expression rewrite (#9492)

fix #9482
This commit is contained in:
丶远方 2023-10-28 15:22:03 +08:00 committed by GitHub
parent edf2572615
commit a75d1c5c62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 15 additions and 7 deletions

View File

@ -2,7 +2,7 @@
exports[`compiler: expression transform > bindingMetadata > inline mode 1`] = ` exports[`compiler: expression transform > bindingMetadata > inline mode 1`] = `
"(_ctx, _cache) => { "(_ctx, _cache) => {
return (_openBlock(), _createElementBlock(\\"div\\", null, _toDisplayString(__props.props) + \\" \\" + _toDisplayString(_unref(setup)) + \\" \\" + _toDisplayString(setupConst) + \\" \\" + _toDisplayString(_ctx.data) + \\" \\" + _toDisplayString(_ctx.options), 1 /* TEXT */)) return (_openBlock(), _createElementBlock(\\"div\\", null, _toDisplayString(__props.props) + \\" \\" + _toDisplayString(_unref(setup)) + \\" \\" + _toDisplayString(setupConst) + \\" \\" + _toDisplayString(_ctx.data) + \\" \\" + _toDisplayString(_ctx.options) + \\" \\" + _toDisplayString(isNaN.value), 1 /* TEXT */))
}" }"
`; `;
@ -10,6 +10,6 @@ exports[`compiler: expression transform > bindingMetadata > non-inline mode 1`]
"const { toDisplayString: _toDisplayString, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { toDisplayString: _toDisplayString, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache, $props, $setup, $data, $options) { return function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock(\\"div\\", null, _toDisplayString($props.props) + \\" \\" + _toDisplayString($setup.setup) + \\" \\" + _toDisplayString($data.data) + \\" \\" + _toDisplayString($options.options), 1 /* TEXT */)) return (_openBlock(), _createElementBlock(\\"div\\", null, _toDisplayString($props.props) + \\" \\" + _toDisplayString($setup.setup) + \\" \\" + _toDisplayString($data.data) + \\" \\" + _toDisplayString($options.options) + \\" \\" + _toDisplayString($setup.isNaN), 1 /* TEXT */))
}" }"
`; `;

View File

@ -506,7 +506,8 @@ describe('compiler: expression transform', () => {
data: BindingTypes.DATA, data: BindingTypes.DATA,
options: BindingTypes.OPTIONS, options: BindingTypes.OPTIONS,
reactive: BindingTypes.SETUP_REACTIVE_CONST, reactive: BindingTypes.SETUP_REACTIVE_CONST,
literal: BindingTypes.LITERAL_CONST literal: BindingTypes.LITERAL_CONST,
isNaN: BindingTypes.SETUP_REF
} }
function compileWithBindingMetadata( function compileWithBindingMetadata(
@ -522,10 +523,11 @@ describe('compiler: expression transform', () => {
test('non-inline mode', () => { test('non-inline mode', () => {
const { code } = compileWithBindingMetadata( const { code } = compileWithBindingMetadata(
`<div>{{ props }} {{ setup }} {{ data }} {{ options }}</div>` `<div>{{ props }} {{ setup }} {{ data }} {{ options }} {{ isNaN }}</div>`
) )
expect(code).toMatch(`$props.props`) expect(code).toMatch(`$props.props`)
expect(code).toMatch(`$setup.setup`) expect(code).toMatch(`$setup.setup`)
expect(code).toMatch(`$setup.isNaN`)
expect(code).toMatch(`$data.data`) expect(code).toMatch(`$data.data`)
expect(code).toMatch(`$options.options`) expect(code).toMatch(`$options.options`)
expect(code).toMatch(`_ctx, _cache, $props, $setup, $data, $options`) expect(code).toMatch(`_ctx, _cache, $props, $setup, $data, $options`)
@ -534,7 +536,7 @@ describe('compiler: expression transform', () => {
test('inline mode', () => { test('inline mode', () => {
const { code } = compileWithBindingMetadata( const { code } = compileWithBindingMetadata(
`<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }}</div>`, `<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</div>`,
{ inline: true } { inline: true }
) )
expect(code).toMatch(`__props.props`) expect(code).toMatch(`__props.props`)
@ -542,6 +544,7 @@ describe('compiler: expression transform', () => {
expect(code).toMatch(`_toDisplayString(setupConst)`) expect(code).toMatch(`_toDisplayString(setupConst)`)
expect(code).toMatch(`_ctx.data`) expect(code).toMatch(`_ctx.data`)
expect(code).toMatch(`_ctx.options`) expect(code).toMatch(`_ctx.options`)
expect(code).toMatch(`isNaN.value`)
expect(code).toMatchSnapshot() expect(code).toMatchSnapshot()
}) })

View File

@ -227,10 +227,15 @@ export function processExpression(
const isScopeVarReference = context.identifiers[rawExp] const isScopeVarReference = context.identifiers[rawExp]
const isAllowedGlobal = isGloballyAllowed(rawExp) const isAllowedGlobal = isGloballyAllowed(rawExp)
const isLiteral = isLiteralWhitelisted(rawExp) const isLiteral = isLiteralWhitelisted(rawExp)
if (!asParams && !isScopeVarReference && !isAllowedGlobal && !isLiteral) { if (
!asParams &&
!isScopeVarReference &&
!isLiteral &&
(!isAllowedGlobal || bindingMetadata[rawExp])
) {
// const bindings exposed from setup can be skipped for patching but // const bindings exposed from setup can be skipped for patching but
// cannot be hoisted to module scope // cannot be hoisted to module scope
if (isConst(bindingMetadata[node.content])) { if (isConst(bindingMetadata[rawExp])) {
node.constType = ConstantTypes.CAN_SKIP_PATCH node.constType = ConstantTypes.CAN_SKIP_PATCH
} }
node.content = rewriteIdentifier(rawExp) node.content = rewriteIdentifier(rawExp)