From be2b1d3c2f16de8dc6e2a22f65fefaa2d25ec3ee Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 25 Jun 2021 13:14:49 -0400 Subject: [PATCH] feat(sfc): defineExpose --- .../__snapshots__/compileScript.spec.ts.snap | 154 +++++++++--------- .../__snapshots__/cssVars.spec.ts.snap | 8 +- .../__tests__/compileScript.spec.ts | 47 +++++- packages/compiler-sfc/src/compileScript.ts | 75 ++++++--- 4 files changed, 177 insertions(+), 107 deletions(-) diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap index a4738da0..d65806a4 100644 --- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap @@ -6,8 +6,8 @@ exports[`SFC compile + `) + assertCode(content) + // should remove defineOptions import and call + expect(content).not.toMatch('defineExpose') + // should generate correct setup signature + expect(content).toMatch(`setup(__props, { expose }) {`) + // should replace callee + expect(content).toMatch(/\bexpose\(\{ foo: 123 \}\)/) + }) + describe(' + `, + { inlineTemplate: true } + ) + assertCode(content) + expect(content).toMatch(`setup(__props, { expose })`) + expect(content).toMatch(`expose({ count })`) }) test('referencing scope components and directives', () => { @@ -456,10 +488,9 @@ const emit = defineEmits(['a', 'b']) `) assertCode(content) expect(content).toMatch(`export default _defineComponent({ - expose: [], props: { foo: String }, emits: ['a', 'b'], - setup(__props, { emit }) {`) + setup(__props, { expose, emit }) {`) }) test('defineProps w/ type', () => { diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index a56888a1..08f48634 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -37,6 +37,7 @@ import { rewriteDefault } from './rewriteDefault' const DEFINE_PROPS = 'defineProps' const DEFINE_EMIT = 'defineEmit' const DEFINE_EMITS = 'defineEmits' +const DEFINE_EXPOSE = 'defineExpose' export interface SFCScriptCompileOptions { /** @@ -188,6 +189,7 @@ export function compileScript( let defaultExport: Node | undefined let hasDefinePropsCall = false let hasDefineEmitCall = false + let hasDefineExposeCall = false let propsRuntimeDecl: Node | undefined let propsTypeDecl: TSTypeLiteral | undefined let propsIdentifier: string | undefined @@ -324,6 +326,17 @@ export function compileScript( return false } + function processDefineExpose(node: Node): boolean { + if (isCallOf(node, DEFINE_EXPOSE)) { + if (hasDefineExposeCall) { + error(`duplicate ${DEFINE_EXPOSE}() call`, node) + } + hasDefineExposeCall = true + return true + } + return false + } + function checkInvalidScopeReference(node: Node | undefined, method: string) { if (!node) return walkIdentifiers(node, id => { @@ -633,7 +646,8 @@ export function compileScript( source === 'vue' && (imported === DEFINE_PROPS || imported === DEFINE_EMIT || - imported === DEFINE_EMITS) + imported === DEFINE_EMITS || + imported === DEFINE_EXPOSE) ) { removeSpecifier(i) } else if (existing) { @@ -657,14 +671,24 @@ export function compileScript( } } - // process `defineProps` and `defineEmit(s)` calls - if ( - node.type === 'ExpressionStatement' && - (processDefineProps(node.expression) || - processDefineEmits(node.expression)) - ) { - s.remove(node.start! + startOffset, node.end! + startOffset) + if (node.type === 'ExpressionStatement') { + // process `defineProps` and `defineEmit(s)` calls + if ( + processDefineProps(node.expression) || + processDefineEmits(node.expression) + ) { + s.remove(node.start! + startOffset, node.end! + startOffset) + } else if (processDefineExpose(node.expression)) { + // defineExpose({}) -> expose({}) + const callee = (node.expression as CallExpression).callee + s.overwrite( + callee.start! + startOffset, + callee.end! + startOffset, + 'expose' + ) + } } + if (node.type === 'VariableDeclaration' && !node.declare) { for (const decl of node.declarations) { if (decl.init) { @@ -863,18 +887,21 @@ export function compileScript( if (propsIdentifier) { s.prependRight(startOffset, `\nconst ${propsIdentifier} = __props`) } + + const destructureElements = + hasDefineExposeCall || !options.inlineTemplate ? [`expose`] : [] if (emitIdentifier) { - args += - emitIdentifier === `emit` ? `, { emit }` : `, { emit: ${emitIdentifier} }` + destructureElements.push( + emitIdentifier === `emit` ? `emit` : `emit: ${emitIdentifier}` + ) + } + if (destructureElements.length) { + args += `, { ${destructureElements.join(', ')} }` if (emitTypeDecl) { - args += `: { - emit: (${scriptSetup.content.slice( - emitTypeDecl.start!, - emitTypeDecl.end! - )}), - slots: any, - attrs: any - }` + args += `: { emit: (${scriptSetup.content.slice( + emitTypeDecl.start!, + emitTypeDecl.end! + )}), expose: any, slots: any, attrs: any }` } } @@ -957,8 +984,7 @@ export function compileScript( s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`) // 11. finalize default export - // expose: [] makes