fix(compiler-core): avoid rewriting scope variables in inline for loops (#7245)

close #7238
This commit is contained in:
edison 2023-11-09 17:20:54 +08:00 committed by GitHub
parent d11e978fc9
commit a2d810eb40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 0 deletions

View File

@ -13,3 +13,45 @@ 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) + \\" \\" + _toDisplayString($setup.isNaN), 1 /* TEXT */)) return (_openBlock(), _createElementBlock(\\"div\\", null, _toDisplayString($props.props) + \\" \\" + _toDisplayString($setup.setup) + \\" \\" + _toDisplayString($data.data) + \\" \\" + _toDisplayString($options.options) + \\" \\" + _toDisplayString($setup.isNaN), 1 /* TEXT */))
}" }"
`; `;
exports[`compiler: expression transform > bindingMetadata > should not prefix temp variable of for loop 1`] = `
"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock(\\"div\\", {
onClick: () => {
for (let i = 0; i < _ctx.list.length; i++) {
_ctx.log(i)
}
}
}, null, 8 /* PROPS */, [\\"onClick\\"]))
}"
`;
exports[`compiler: expression transform > bindingMetadata > should not prefix temp variable of for...in 1`] = `
"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock(\\"div\\", {
onClick: () => {
for (const x in _ctx.list) {
_ctx.log(x)
}
}
}, null, 8 /* PROPS */, [\\"onClick\\"]))
}"
`;
exports[`compiler: expression transform > bindingMetadata > should not prefix temp variable of for...of 1`] = `
"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock(\\"div\\", {
onClick: () => {
for (const x of _ctx.list) {
_ctx.log(x)
}
}
}, null, 8 /* PROPS */, [\\"onClick\\"]))
}"
`;

View File

@ -534,6 +534,42 @@ describe('compiler: expression transform', () => {
expect(code).toMatchSnapshot() expect(code).toMatchSnapshot()
}) })
test('should not prefix temp variable of for...in', () => {
const { code } = compileWithBindingMetadata(
`<div @click="() => {
for (const x in list) {
log(x)
}
}"/>`
)
expect(code).not.toMatch(`_ctx.x`)
expect(code).toMatchSnapshot()
})
test('should not prefix temp variable of for...of', () => {
const { code } = compileWithBindingMetadata(
`<div @click="() => {
for (const x of list) {
log(x)
}
}"/>`
)
expect(code).not.toMatch(`_ctx.x`)
expect(code).toMatchSnapshot()
})
test('should not prefix temp variable of for loop', () => {
const { code } = compileWithBindingMetadata(
`<div @click="() => {
for (let i = 0; i < list.length; i++) {
log(i)
}
}"/>`
)
expect(code).not.toMatch(`_ctx.i`)
expect(code).toMatchSnapshot()
})
test('inline mode', () => { test('inline mode', () => {
const { code } = compileWithBindingMetadata( const { code } = compileWithBindingMetadata(
`<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</div>`, `<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</div>`,

View File

@ -165,6 +165,19 @@ export function walkBlockDeclarations(
) { ) {
if (stmt.declare || !stmt.id) continue if (stmt.declare || !stmt.id) continue
onIdent(stmt.id) onIdent(stmt.id)
} else if (
stmt.type === 'ForOfStatement' ||
stmt.type === 'ForInStatement' ||
stmt.type === 'ForStatement'
) {
const variable = stmt.type === 'ForStatement' ? stmt.init : stmt.left
if (variable && variable.type === 'VariableDeclaration') {
for (const decl of variable.declarations) {
for (const id of extractIdentifiers(decl.id)) {
onIdent(id)
}
}
}
} }
} }
} }