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
+}