From 049432379537da4f69bedb699003d8ae90f04093 Mon Sep 17 00:00:00 2001 From: zhiyuanzmj <32807958+zhiyuanzmj@users.noreply.github.com> Date: Sat, 13 Jan 2024 18:30:03 +0800 Subject: [PATCH] feat(compiler-vapor): support `expressionPlugins` for generate (#91) --- .../__tests__/transforms/vOn.spec.ts | 33 +++++++++---------- packages/compiler-vapor/src/compile.ts | 7 ++-- packages/compiler-vapor/src/generate.ts | 18 ++++++---- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts index 6fae1713f..7705e1e18 100644 --- a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts @@ -269,25 +269,22 @@ describe('v-on', () => { expect(code).contains('_on(n1, "click", $event => _ctx.foo($event))') }) - test.fails( - 'should NOT wrap as function if expression is already function expression (with Typescript)', - () => { - const { ir, code } = compileWithVOn( - `
`, - { expressionPlugins: ['typescript'] }, - ) - - expect(ir.operation).toMatchObject([ - { - type: IRNodeTypes.SET_EVENT, - value: { content: '(e: any): any => foo(e)' }, - }, - ]) + test('should NOT wrap as function if expression is already function expression (with Typescript)', () => { + const { ir, code } = compileWithVOn( + `
`, + { expressionPlugins: ['typescript'] }, + ) - expect(code).matchSnapshot() - expect(code).contains('_on(n1, "click", e => _ctx.foo(e))') - }, - ) + expect(ir.operation).toMatchObject([ + { + type: IRNodeTypes.SET_EVENT, + value: { content: '(e: any): any => foo(e)' }, + }, + ]) + + expect(code).matchSnapshot() + expect(code).contains('_on(n1, "click", (e: any): any => _ctx.foo(e))') + }) test('should NOT wrap as function if expression is already function expression (with newlines)', () => { const { ir, code } = compileWithVOn( diff --git a/packages/compiler-vapor/src/compile.ts b/packages/compiler-vapor/src/compile.ts index dd7aad5cf..6d304ae20 100644 --- a/packages/compiler-vapor/src/compile.ts +++ b/packages/compiler-vapor/src/compile.ts @@ -61,13 +61,16 @@ export function compile( if (!__BROWSER__ && options.isTS) { const { expressionPlugins } = options if (!expressionPlugins || !expressionPlugins.includes('typescript')) { - options.expressionPlugins = [...(expressionPlugins || []), 'typescript'] + resolvedOptions.expressionPlugins = [ + ...(expressionPlugins || []), + 'typescript', + ] } } const ir = transform( ast, - extend({}, options, { + extend({}, resolvedOptions, { nodeTransforms: [ ...nodeTransforms, ...(options.nodeTransforms || []), // user transforms diff --git a/packages/compiler-vapor/src/generate.ts b/packages/compiler-vapor/src/generate.ts index 9d916146f..9b6543e1e 100644 --- a/packages/compiler-vapor/src/generate.ts +++ b/packages/compiler-vapor/src/generate.ts @@ -1,6 +1,6 @@ import { + type CodegenOptions as BaseCodegenOptions, BindingTypes, - type CodegenOptions, type CodegenResult, NewlineType, type Position, @@ -33,6 +33,11 @@ import { import { SourceMapGenerator } from 'source-map-js' import { camelize, isGloballyAllowed, isString, makeMap } from '@vue/shared' import type { Identifier } from '@babel/types' +import type { ParserPlugin } from '@babel/parser' + +interface CodegenOptions extends BaseCodegenOptions { + expressionPlugins?: ParserPlugin[] +} // TODO: share this with compiler-core const fnExpRE = @@ -94,6 +99,7 @@ function createCodegenContext( inSSR = false, inline = false, bindingMetadata = {}, + expressionPlugins = [], }: CodegenOptions, ) { const { helpers, vaporHelpers } = ir @@ -111,6 +117,7 @@ function createCodegenContext( isTS, inSSR, bindingMetadata, + expressionPlugins, inline, source: ir.source, @@ -513,7 +520,7 @@ function genSetEvent(oper: SetEventIRNode, context: CodegenContext) { ;(keys.length ? pushWithKeys : pushNoop)(() => (nonKeys.length ? pushWithModifiers : pushNoop)(() => { - genEventHandler() + genEventHandler(context) }), ) }, @@ -522,13 +529,10 @@ function genSetEvent(oper: SetEventIRNode, context: CodegenContext) { (() => push(`{ ${options.map((v) => `${v}: true`).join(', ')} }`)), ) - function genEventHandler() { + function genEventHandler(context: CodegenContext) { const exp = oper.value if (exp && exp.content.trim()) { - const isMemberExp = isMemberExpression(exp.content, { - // TODO: expression plugins - expressionPlugins: [], - }) + const isMemberExp = isMemberExpression(exp.content, context) const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content)) const hasMultipleStatements = exp.content.includes(`;`)