From: Evan You Date: Fri, 12 Jan 2024 14:06:46 +0000 (+0800) Subject: dx(defineModel): warn against reference of setup scope variables in defineModel options X-Git-Tag: v3.4.11~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c60479146aad8c0c33a6e4be186b1cff45bd1871;p=thirdparty%2Fvuejs%2Fcore.git dx(defineModel): warn against reference of setup scope variables in defineModel options close #10093 --- diff --git a/packages/compiler-core/src/babelUtils.ts b/packages/compiler-core/src/babelUtils.ts index 0a7f48af90..b12a6d9b47 100644 --- a/packages/compiler-core/src/babelUtils.ts +++ b/packages/compiler-core/src/babelUtils.ts @@ -50,7 +50,7 @@ export function walkIdentifiers( } } else if ( node.type === 'ObjectProperty' && - parent!.type === 'ObjectPattern' + parent?.type === 'ObjectPattern' ) { // mark property in destructure pattern ;(node as any).inPattern = true diff --git a/packages/compiler-sfc/__tests__/compileScript.spec.ts b/packages/compiler-sfc/__tests__/compileScript.spec.ts index 7c21816eb7..2b9acbc7fd 100644 --- a/packages/compiler-sfc/__tests__/compileScript.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript.spec.ts @@ -953,6 +953,38 @@ describe('SFC compile `).content, ) }) + + test('defineModel() referencing local var', () => { + expect(() => + compile(``), + ).toThrow(`cannot reference locally declared variables`) + + // allow const + expect(() => + compile(``), + ).not.toThrow(`cannot reference locally declared variables`) + + // allow in get/set + expect(() => + compile(``), + ).not.toThrow(`cannot reference locally declared variables`) + }) }) }) diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index b0b79f8c88..69beb2af79 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -671,6 +671,11 @@ export function compileScript( checkInvalidScopeReference(ctx.propsDestructureDecl, DEFINE_PROPS) checkInvalidScopeReference(ctx.emitsRuntimeDecl, DEFINE_EMITS) checkInvalidScopeReference(ctx.optionsRuntimeDecl, DEFINE_OPTIONS) + for (const { runtimeOptionNodes } of Object.values(ctx.modelDecls)) { + for (const node of runtimeOptionNodes) { + checkInvalidScopeReference(node, DEFINE_MODEL) + } + } // 5. remove non-script content if (script) { diff --git a/packages/compiler-sfc/src/script/defineModel.ts b/packages/compiler-sfc/src/script/defineModel.ts index b94b799462..24fd0780ea 100644 --- a/packages/compiler-sfc/src/script/defineModel.ts +++ b/packages/compiler-sfc/src/script/defineModel.ts @@ -15,6 +15,7 @@ export interface ModelDecl { type: TSType | undefined options: string | undefined identifier: string | undefined + runtimeOptionNodes: Node[] } export function processDefineModel( @@ -48,6 +49,7 @@ export function processDefineModel( let optionsString = options && ctx.getString(options) let optionsRemoved = !options + const runtimeOptionNodes: Node[] = [] if ( options && @@ -75,6 +77,8 @@ export function processDefineModel( // remove prop options from runtime options removed++ ctx.s.remove(ctx.startOffset! + start, ctx.startOffset! + end) + // record prop options for invalid scope var reference check + runtimeOptionNodes.push(p) } } if (removed === options.properties.length) { @@ -89,6 +93,7 @@ export function processDefineModel( ctx.modelDecls[modelName] = { type, options: optionsString, + runtimeOptionNodes, identifier: declId && declId.type === 'Identifier' ? declId.name : undefined, }