diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineDirective.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineDirective.spec.ts.snap new file mode 100644 index 00000000000..274be42e23d --- /dev/null +++ b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineDirective.spec.ts.snap @@ -0,0 +1,67 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`defineProps > basic usage 2`] = ` +" +export default { + setup(__props, { expose: __expose }) { + __expose(); + + const vTest = { created(){} } + +return { vTest } +} + +}" +`; + +exports[`defineProps > use of multiple define micro 2`] = ` +" +export default { + props: { + bar: String + }, + setup(__props, { expose: __expose }) { + __expose(); + + const vTest = { created(){} } + const props = __props + const vFoo = { mounted(){} } + +return { vTest, props, vFoo } +} + +}" +`; + +exports[`defineProps > use with other micro 2`] = ` +" +export default { + props: { + bar: String + }, + setup(__props, { expose: __expose }) { + __expose(); + + const vTest = { created(){} } + const props = __props + +return { vTest, props } +} + +}" +`; + +exports[`defineProps > with typescript 2`] = ` +"import { defineComponent as _defineComponent } from 'vue' + +export default /*#__PURE__*/_defineComponent({ + setup(__props, { expose: __expose }) { + __expose(); + + const vTest = { created(){} } + +return { vTest } +} + +})" +`; diff --git a/packages/compiler-sfc/__tests__/compileScript/defineDirective.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineDirective.spec.ts new file mode 100644 index 00000000000..54c1331ba0b --- /dev/null +++ b/packages/compiler-sfc/__tests__/compileScript/defineDirective.spec.ts @@ -0,0 +1,125 @@ +import { assertCode, compileSFCScript as compile } from '../utils' + +describe('defineProps', () => { + test('basic usage', () => { + const { content } = compile(` + + `) + expect(content).toMatchInlineSnapshot(` + " + export default { + setup(__props, { expose: __expose }) { + __expose(); + + const vTest = { created(){} } + + return { vTest } + } + + }" + `) + + assertCode(content) + expect(content).not.toMatch('defineDirective') + expect(content).toMatch('const vTest = { created(){} }') + expect(content).toMatch('return { vTest }') + }) + + test('with typescript', () => { + const { content } = compile(` + + `) + expect(content).toMatchInlineSnapshot(` + "import { defineComponent as _defineComponent } from 'vue' + + export default /*#__PURE__*/_defineComponent({ + setup(__props, { expose: __expose }) { + __expose(); + + const vTest = { created(){} } + + return { vTest } + } + + })" + `) + + assertCode(content) + expect(content).not.toMatch('defineDirective') + expect(content).toMatch('const vTest = { created(){} }') + expect(content).toMatch('return { vTest }') + }) + + test('use with other micro', () => { + const { content } = compile(` + + `) + expect(content).toMatchInlineSnapshot(` + " + export default { + props: { + bar: String + }, + setup(__props, { expose: __expose }) { + __expose(); + + const vTest = { created(){} } + const props = __props + + return { vTest, props } + } + + }" + `) + + assertCode(content) + expect(content).not.toMatch('defineDirective') + expect(content).toMatch('const vTest = { created(){} }') + expect(content).toMatch('return { vTest, props }') + }) + + test('use of multiple define micro', () => { + const { content } = compile(` + + `) + expect(content).toMatchInlineSnapshot(` + " + export default { + props: { + bar: String + }, + setup(__props, { expose: __expose }) { + __expose(); + + const vTest = { created(){} } + const props = __props + const vFoo = { mounted(){} } + + return { vTest, props, vFoo } + } + + }" + `) + + assertCode(content) + expect(content).not.toMatch('defineDirective') + expect(content).toMatch('const vTest = { created(){} }') + expect(content).toMatch('const vFoo = { mounted(){} }') + expect(content).toMatch('return { vTest, props, vFoo }') + }) +}) diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index d4131d5c61d..17e899dae92 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -55,6 +55,7 @@ import { getImportedName, isCallOf, isLiteralNode } from './script/utils' import { analyzeScriptBindings } from './script/analyzeScriptBindings' import { isImportUsed } from './script/importUsageCheck' import { processAwait } from './script/topLevelAwait' +import { processDefineDirective } from './script/defineDirective' export interface SFCScriptCompileOptions { /** @@ -523,13 +524,14 @@ export function compileScript( ) } - // defineProps / defineEmits + // defineProps / defineEmits / defineDirective const isDefineProps = processDefineProps(ctx, init, decl.id) const isDefineEmits = !isDefineProps && processDefineEmits(ctx, init, decl.id) !isDefineEmits && (processDefineSlots(ctx, init, decl.id) || - processDefineModel(ctx, init, decl.id)) + processDefineModel(ctx, init, decl.id) || + processDefineDirective(ctx, init, decl.id)) if ( isDefineProps && diff --git a/packages/compiler-sfc/src/script/defineDirective.ts b/packages/compiler-sfc/src/script/defineDirective.ts new file mode 100644 index 00000000000..5044b6d6624 --- /dev/null +++ b/packages/compiler-sfc/src/script/defineDirective.ts @@ -0,0 +1,29 @@ +import type { ScriptCompileContext } from './context' +import type { LVal, Node } from '@babel/types' +import { isCallOf } from './utils' +import { unwrapTSNode } from '@vue/compiler-dom' + +export const DEFINE_DIRECTIVE = 'defineDirective' + +export function processDefineDirective( + ctx: ScriptCompileContext, + node: Node, + declId?: LVal, +) { + if (!isCallOf(node, DEFINE_DIRECTIVE)) { + return false + } + let options: Node | undefined + const arg0 = node.arguments[0] && unwrapTSNode(node.arguments[0]) + options = arg0 + + let optionsString = options && ctx.getString(options) + + ctx.s.overwrite( + ctx.startOffset! + node.start!, + ctx.startOffset! + node.end!, + optionsString, + ) + + return true +} diff --git a/packages/runtime-core/src/apiSetupHelpers.ts b/packages/runtime-core/src/apiSetupHelpers.ts index e5f79444da0..e64eeb86fe0 100644 --- a/packages/runtime-core/src/apiSetupHelpers.ts +++ b/packages/runtime-core/src/apiSetupHelpers.ts @@ -30,6 +30,7 @@ import type { import { warn } from './warning' import type { SlotsType, StrictUnwrapSlotsType } from './componentSlots' import type { Ref } from '@vue/reactivity' +import type { Directive } from './directives' // dev only const warnRuntimeUsage = (method: string) => @@ -479,3 +480,13 @@ export function withAsyncContext(getAwaitable: () => any) { } return [awaitable, () => setCurrentInstance(ctx)] } + +export function defineDirective( + options: Directive, +): Directive +export function defineDirective() { + if (__DEV__) { + warnRuntimeUsage('defineDirective') + } + return null as any +}