From cc5e1d290b6e62a0eed7033eab46409b311b6c6f Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Mon, 26 Apr 2021 12:30:33 +0800 Subject: [PATCH] fix(compiler-core): improve the isMemberExpression function --- .../compiler-core/__tests__/utils.spec.ts | 22 ++++++++++++++++++- packages/compiler-core/src/utils.ts | 8 +++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/compiler-core/__tests__/utils.spec.ts b/packages/compiler-core/__tests__/utils.spec.ts index b5d1bea04c9..4fc4e8d16a5 100644 --- a/packages/compiler-core/__tests__/utils.spec.ts +++ b/packages/compiler-core/__tests__/utils.spec.ts @@ -1,5 +1,9 @@ import { Position } from '../src/ast' -import { getInnerRange, advancePositionWithClone } from '../src/utils' +import { + getInnerRange, + advancePositionWithClone, + isMemberExpression +} from '../src/utils' function p(line: number, column: number, offset: number): Position { return { column, line, offset } @@ -67,3 +71,19 @@ describe('getInnerRange', () => { expect(loc2.end.offset).toBe(7) }) }) + +test('isMemberExpression', () => { + // should work + expect(isMemberExpression('obj.foo')).toBe(true) + expect(isMemberExpression('obj[foo]')).toBe(true) + expect(isMemberExpression('obj[arr[0]]')).toBe(true) + expect(isMemberExpression('obj[arr[ret.bar]]')).toBe(true) + expect(isMemberExpression('obj[arr[ret[bar]]]')).toBe(true) + expect(isMemberExpression('obj[arr[ret[bar]]].baz')).toBe(true) + expect(isMemberExpression('obj[1 + 1]')).toBe(true) + // should warning + expect(isMemberExpression('obj[foo')).toBe(false) + expect(isMemberExpression('objfoo]')).toBe(false) + expect(isMemberExpression('obj[arr[0]')).toBe(false) + expect(isMemberExpression('obj[arr0]]')).toBe(false) +}) diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index b65c812a6e4..3655d066ac7 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -56,10 +56,14 @@ const nonIdentifierRE = /^\d|[^\$\w]/ export const isSimpleIdentifier = (name: string): boolean => !nonIdentifierRE.test(name) -const memberExpRE = /^[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*(?:\s*\.\s*[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*|\[[^\]]+\])*$/ +const memberExpRE = /^[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*(?:\s*\.\s*[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*|\[(.+)\])*$/ export const isMemberExpression = (path: string): boolean => { if (!path) return false - return memberExpRE.test(path.trim()) + const matched = memberExpRE.exec(path.trim()) + if (!matched) return false + if (!matched[1]) return true + if (!/[\[\]]/.test(matched[1])) return true + return isMemberExpression(matched[1].trim()) } export function getInnerRange(