fix(compiler-core): more robust member expression check when running in node
fix #4640
This commit is contained in:
@@ -41,7 +41,10 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||
bindingType &&
|
||||
bindingType !== BindingTypes.SETUP_CONST
|
||||
|
||||
if (!expString.trim() || (!isMemberExpression(expString) && !maybeRef)) {
|
||||
if (
|
||||
!expString.trim() ||
|
||||
(!isMemberExpression(expString, context) && !maybeRef)
|
||||
) {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc)
|
||||
)
|
||||
|
||||
@@ -73,7 +73,7 @@ export const transformOn: DirectiveTransform = (
|
||||
}
|
||||
let shouldCache: boolean = context.cacheHandlers && !exp && !context.inVOnce
|
||||
if (exp) {
|
||||
const isMemberExp = isMemberExpression(exp.content)
|
||||
const isMemberExp = isMemberExpression(exp.content, context)
|
||||
const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content))
|
||||
const hasMultipleStatements = exp.content.includes(`;`)
|
||||
|
||||
|
||||
@@ -42,8 +42,16 @@ import {
|
||||
WITH_MEMO,
|
||||
OPEN_BLOCK
|
||||
} from './runtimeHelpers'
|
||||
import { isString, isObject, hyphenate, extend } from '@vue/shared'
|
||||
import {
|
||||
isString,
|
||||
isObject,
|
||||
hyphenate,
|
||||
extend,
|
||||
babelParserDefaultPlugins
|
||||
} from '@vue/shared'
|
||||
import { PropsExpression } from './transforms/transformElement'
|
||||
import { parseExpression } from '@babel/parser'
|
||||
import { Expression } from '@babel/types'
|
||||
|
||||
export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
|
||||
p.type === NodeTypes.SIMPLE_EXPRESSION && p.isStatic
|
||||
@@ -84,7 +92,7 @@ const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g
|
||||
* inside square brackets), but it's ok since these are only used on template
|
||||
* expressions and false positives are invalid expressions in the first place.
|
||||
*/
|
||||
export const isMemberExpression = (path: string): boolean => {
|
||||
export const isMemberExpressionBrowser = (path: string): boolean => {
|
||||
// remove whitespaces around . or [ first
|
||||
path = path.trim().replace(whitespaceRE, s => s.trim())
|
||||
|
||||
@@ -153,6 +161,35 @@ export const isMemberExpression = (path: string): boolean => {
|
||||
return !currentOpenBracketCount && !currentOpenParensCount
|
||||
}
|
||||
|
||||
export const isMemberExpressionNode = (
|
||||
path: string,
|
||||
context: TransformContext
|
||||
): boolean => {
|
||||
path = path.trim()
|
||||
if (!validFirstIdentCharRE.test(path[0])) {
|
||||
return false
|
||||
}
|
||||
try {
|
||||
let ret: Expression = parseExpression(path, {
|
||||
plugins: [...context.expressionPlugins, ...babelParserDefaultPlugins]
|
||||
})
|
||||
if (ret.type === 'TSAsExpression' || ret.type === 'TSTypeAssertion') {
|
||||
ret = ret.expression
|
||||
}
|
||||
return (
|
||||
ret.type === 'MemberExpression' ||
|
||||
ret.type === 'OptionalMemberExpression' ||
|
||||
ret.type === 'Identifier'
|
||||
)
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const isMemberExpression = __BROWSER__
|
||||
? isMemberExpressionBrowser
|
||||
: isMemberExpressionNode
|
||||
|
||||
export function getInnerRange(
|
||||
loc: SourceLocation,
|
||||
offset: number,
|
||||
|
||||
Reference in New Issue
Block a user