Browse Source
feat(compiler): better warning for invalid expressions in function/browser mode
feat(compiler): better warning for invalid expressions in function/browser mode
fix #1266pull/1355/head

7 changed files with 159 additions and 1 deletions
-
4packages/compiler-core/src/compile.ts
-
7packages/compiler-core/src/transforms/transformExpression.ts
-
25packages/compiler-core/src/transforms/vFor.ts
-
5packages/compiler-core/src/transforms/vIf.ts
-
10packages/compiler-core/src/transforms/vOn.ts
-
49packages/compiler-core/src/transforms/validateExpression.ts
-
60packages/compiler-core/src/validateExpression.ts
@ -0,0 +1,49 @@ |
|||
import { NodeTransform, TransformContext } from '../transform' |
|||
import { NodeTypes, SimpleExpressionNode } from '../ast' |
|||
|
|||
/** |
|||
* When using the runtime compiler in function mode, some expressions will |
|||
* become invalid (e.g. using keyworkds like `class` in expressions) so we need |
|||
* to detect them. |
|||
* |
|||
* This transform is browser-only and dev-only. |
|||
*/ |
|||
export const validateExpression: NodeTransform = (node, context) => { |
|||
if (node.type === NodeTypes.INTERPOLATION) { |
|||
validateBrowserExpression(node.content as SimpleExpressionNode, context) |
|||
} else if (node.type === NodeTypes.ELEMENT) { |
|||
// handle directives on element
|
|||
for (let i = 0; i < node.props.length; i++) { |
|||
const dir = node.props[i] |
|||
// do not process for v-on & v-for since they are special handled
|
|||
if (dir.type === NodeTypes.DIRECTIVE && dir.name !== 'for') { |
|||
const exp = dir.exp |
|||
const arg = dir.arg |
|||
// do not process exp if this is v-on:arg - we need special handling
|
|||
// for wrapping inline statements.
|
|||
if ( |
|||
exp && |
|||
exp.type === NodeTypes.SIMPLE_EXPRESSION && |
|||
!(dir.name === 'on' && arg) |
|||
) { |
|||
validateBrowserExpression( |
|||
exp, |
|||
context, |
|||
// slot args must be processed as function params
|
|||
dir.name === 'slot' |
|||
) |
|||
} |
|||
if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION && !arg.isStatic) { |
|||
validateBrowserExpression(arg, context) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
export function validateBrowserExpression( |
|||
node: SimpleExpressionNode, |
|||
context: TransformContext, |
|||
asParams = false, |
|||
asRawStatements = false |
|||
) {} |
@ -0,0 +1,60 @@ |
|||
// these keywords should not appear inside expressions, but operators like
|
|||
|
|||
import { SimpleExpressionNode } from './ast' |
|||
import { TransformContext } from './transform' |
|||
import { createCompilerError, ErrorCodes } from './errors' |
|||
|
|||
// typeof, instanceof and in are allowed
|
|||
const prohibitedKeywordRE = new RegExp( |
|||
'\\b' + |
|||
( |
|||
'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' + |
|||
'super,throw,while,yield,delete,export,import,return,switch,default,' + |
|||
'extends,finally,continue,debugger,function,arguments,typeof,void' |
|||
) |
|||
.split(',') |
|||
.join('\\b|\\b') + |
|||
'\\b' |
|||
) |
|||
|
|||
// strip strings in expressions
|
|||
const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g |
|||
|
|||
/** |
|||
* Validate a non-prefixed expression. |
|||
* This is only called when using the in-browser runtime compiler since it |
|||
* doesn't prefix expressions. |
|||
*/ |
|||
export function validateBrowserExpression( |
|||
node: SimpleExpressionNode, |
|||
context: TransformContext, |
|||
asParams = false, |
|||
asRawStatements = false |
|||
) { |
|||
const exp = node.content |
|||
try { |
|||
new Function( |
|||
asRawStatements |
|||
? ` ${exp} ` |
|||
: `return ${asParams ? `(${exp}) => {}` : `(${exp})`}` |
|||
) |
|||
} catch (e) { |
|||
let message = e.message |
|||
const keywordMatch = exp |
|||
.replace(stripStringRE, '') |
|||
.match(prohibitedKeywordRE) |
|||
if (keywordMatch) { |
|||
message = `avoid using JavaScript keyword as property name: "${ |
|||
keywordMatch[0] |
|||
}"`
|
|||
} |
|||
context.onError( |
|||
createCompilerError( |
|||
ErrorCodes.X_INVALID_EXPRESSION, |
|||
node.loc, |
|||
undefined, |
|||
message |
|||
) |
|||
) |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue