}"
`;
+exports[`compiler: expression transform > should allow leak of var declarations in for loop 1`] = `
+"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
+
+return function render(_ctx, _cache) {
+ return (_openBlock(), _createElementBlock("div", {
+ onClick: () => {
+ for (var i = 0; i < _ctx.list.length; i++) {
+ _ctx.log(i)
+ }
+ _ctx.error(i)
+ }
+ }, null, 8 /* PROPS */, ["onClick"]))
+}"
+`;
+
exports[`compiler: expression transform > should not prefix catch block param 1`] = `
"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
for (let i = 0; i < _ctx.list.length; i++) {
_ctx.log(i)
}
+ _ctx.error(_ctx.i)
}
}, null, 8 /* PROPS */, ["onClick"]))
}"
for (const x in _ctx.list) {
_ctx.log(x)
}
+ _ctx.error(_ctx.x)
}
}, null, 8 /* PROPS */, ["onClick"]))
}"
for (const x of _ctx.list) {
_ctx.log(x)
}
+ _ctx.error(_ctx.x)
}
}, null, 8 /* PROPS */, ["onClick"]))
}"
for (const x in list) {
log(x)
}
+ error(x)
}"/>`,
)
- expect(code).not.toMatch(`_ctx.x`)
+ expect(code).not.toMatch(`log(_ctx.x)`)
+ expect(code).toMatch(`error(_ctx.x)`)
expect(code).toMatchSnapshot()
})
for (const x of list) {
log(x)
}
+ error(x)
}"/>`,
)
- expect(code).not.toMatch(`_ctx.x`)
+ expect(code).not.toMatch(`log(_ctx.x)`)
+ expect(code).toMatch(`error(_ctx.x)`)
expect(code).toMatchSnapshot()
})
for (let i = 0; i < list.length; i++) {
log(i)
}
+ error(i)
}"/>`,
)
- expect(code).not.toMatch(`_ctx.i`)
+ expect(code).not.toMatch(`log(_ctx.i)`)
+ expect(code).toMatch(`error(_ctx.i)`)
+ expect(code).toMatchSnapshot()
+ })
+
+ test('should allow leak of var declarations in for loop', () => {
+ const { code } = compile(
+ `<div @click="() => {
+ for (var i = 0; i < list.length; i++) {
+ log(i)
+ }
+ error(i)
+ }"/>`,
+ )
+ expect(code).not.toMatch(`log(_ctx.i)`)
+ expect(code).not.toMatch(`error(_ctx.i)`)
expect(code).toMatchSnapshot()
})
// do not import runtime methods
import type {
BlockStatement,
+ ForInStatement,
+ ForOfStatement,
+ ForStatement,
Function,
Identifier,
Node,
for (const id of extractIdentifiers(node.param)) {
markScopeIdentifier(node, id, knownIds)
}
+ } else if (isForStatement(node)) {
+ walkForStatement(node, false, id =>
+ markScopeIdentifier(node, id, knownIds),
+ )
}
},
leave(node: Node & { scopeIds?: Set<string> }, parent: Node | null) {
) {
if (stmt.declare || !stmt.id) continue
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)
- }
- }
+ } else if (isForStatement(stmt)) {
+ walkForStatement(stmt, true, onIdent)
+ }
+ }
+}
+
+function isForStatement(
+ stmt: Node,
+): stmt is ForStatement | ForOfStatement | ForInStatement {
+ return (
+ stmt.type === 'ForOfStatement' ||
+ stmt.type === 'ForInStatement' ||
+ stmt.type === 'ForStatement'
+ )
+}
+
+function walkForStatement(
+ stmt: ForStatement | ForOfStatement | ForInStatement,
+ isVar: boolean,
+ onIdent: (id: Identifier) => void,
+) {
+ const variable = stmt.type === 'ForStatement' ? stmt.init : stmt.left
+ if (
+ variable &&
+ variable.type === 'VariableDeclaration' &&
+ (variable.kind === 'var' ? isVar : !isVar)
+ ) {
+ for (const decl of variable.declarations) {
+ for (const id of extractIdentifiers(decl.id)) {
+ onIdent(id)
}
}
}