diff --git a/src/compiler/error-detector.js b/src/compiler/error-detector.js index c516f764..fb42fcbb 100644 --- a/src/compiler/error-detector.js +++ b/src/compiler/error-detector.js @@ -2,6 +2,12 @@ import { dirRE } from './parser/index' +const keywordRE = new RegExp('\\b' + ( + 'do,if,in,for,let,new,try,var,case,else,with,await,break,catch,class,const,' + + 'super,throw,while,yield,delete,export,import,return,switch,typeof,default,' + + 'extends,finally,continue,debugger,function,arguments,instanceof' +).split(',').join('\\b|\\b') + '\\b') + // detect problematic expressions in a template export function detectErrors (ast: ?ASTNode): Array { const errors: Array = [] @@ -32,9 +38,22 @@ function checkNode (node: ASTNode, errors: Array) { } function checkExpression (exp: string, text: string, errors: Array) { - try { - new Function(exp) - } catch (e) { - errors.push(`- invalid expression: ${text}`) + exp = stripToString(exp) + const keywordMatch = exp.match(keywordRE) + if (keywordMatch) { + errors.push( + `- avoid using JavaScript keyword as property name: ` + + `"${keywordMatch[0]}" in expression ${text}` + ) + } else { + try { + new Function(exp) + } catch (e) { + errors.push(`- invalid expression: ${text}`) + } } } + +function stripToString (exp) { + return exp.replace(/^_s\((.*)\)$/, '$1') +} diff --git a/test/unit/features/options/template.spec.js b/test/unit/features/options/template.spec.js index 65ea300c..60305bfa 100644 --- a/test/unit/features/options/template.spec.js +++ b/test/unit/features/options/template.spec.js @@ -53,10 +53,11 @@ describe('Options template', () => { it('warn error in generated function', () => { new Vue({ - template: '
{{ a"" }}
' + template: '
{{ a"" }}{{ do + 1 }}
' }).$mount() expect('failed to compile template').toHaveBeenWarned() expect('invalid expression: v-if="!@"').toHaveBeenWarned() expect('invalid expression: {{ a"" }}').toHaveBeenWarned() + expect('avoid using JavaScript keyword as property name: "do" in expression {{ do + 1 }}').toHaveBeenWarned() }) })