Skip to content

Commit

Permalink
feat(better-define): support dynamic default definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Oct 28, 2022
1 parent e1f7bdc commit b5fa188
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 17 deletions.
7 changes: 7 additions & 0 deletions .changeset/tidy-drinks-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@vue-macros/api': patch
'@vue-macros/better-define': patch
'@vue-macros/common': patch
---

support dynamic default definitions of props
1 change: 0 additions & 1 deletion packages/api/src/vue/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@ export async function handleTSPropsDefinition({
array: true,
object: true,
objectMethod: true,
unary: true,
})
if (!isStatic) return { defaultsAst: defaultsAst as Expression }

Expand Down
2 changes: 1 addition & 1 deletion packages/api/tests/__snapshots__/analyzeSFC.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ exports[`analyzeSFC > defineProps > should resolve referenced type 1`] = `
}
`;
exports[`analyzeSFC > defineProps w/ withDefaults 1`] = `
exports[`analyzeSFC > defineProps w/ withDefaults (static) 1`] = `
{
"bar": Node {
"async": false,
Expand Down
14 changes: 13 additions & 1 deletion packages/api/tests/analyzeSFC.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ describe('analyzeSFC', () => {
})
})

test('defineProps w/ withDefaults', async () => {
test('defineProps w/ withDefaults (static)', async () => {
const { props } = await complie(`withDefaults(defineProps<{
foo: string
bar?(): void
Expand Down Expand Up @@ -396,6 +396,18 @@ describe('analyzeSFC', () => {

snapshot(props!.defaults)
})

test('defineProps w/ withDefaults (dynamic)', async () => {
const { props } = await complie(`withDefaults(defineProps<{
foo: string
bar?: number
}>(), {
['b' + 'ar']: 'bar'
})`)
const defaults = await props!.getRuntimeDefinitions()
expect(defaults.bar.default).toBeUndefined()
expect(props!.defaults).toBeUndefined()
})
test.todo('mutate defaults')

describe('defineEmits', () => {
Expand Down
23 changes: 17 additions & 6 deletions packages/better-define/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,24 @@ export const transformBetterDefine = async (code: string, id: string) => {
})
.join(',\n ')}\n}`

s.overwriteNode(
props.withDefaultsAst || props.definePropsAst,
`defineProps(${runtimeDecls})`,
{
let decl = runtimeDecls
if (props.withDefaultsAst && !props.defaults) {
// dynamic defaults
decl = `_BD_mergeDefaults(${decl}, ${s.sliceNode(
props.withDefaultsAst.arguments[1],
{ offset }
)})`
// add helper
s.prependLeft(
offset,
}
)
`import { mergeDefaults as _BD_mergeDefaults } from 'vue'`
)
}
decl = `defineProps(${decl})`

s.overwriteNode(props.withDefaultsAst || props.definePropsAst, decl, {
offset,
})
}

function processEmits(emits: TSEmits) {
Expand Down
39 changes: 35 additions & 4 deletions packages/better-define/tests/__snapshots__/fixtures.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,42 @@ export { basic as default };
"
`;

exports[`fixtures > tests/fixtures/defaults.vue 1`] = `
exports[`fixtures > tests/fixtures/defaults-dynamic.vue 1`] = `
"import { defineComponent, mergeDefaults, openBlock, createElementBlock } from 'vue';
var _sfc_main = /* @__PURE__ */ defineComponent({
__name: \\"defaults-dynamic\\",
props: mergeDefaults({
foo: { type: String, required: false }
}, {
[\\"foo\\"]: \\"foo\\"
}),
setup(__props) {
return (_ctx, _cache) => {
return openBlock(), createElementBlock(\\"div\\");
};
}
});
var _export_sfc = (sfc, props) => {
const target = sfc.__vccOpts || sfc;
for (const [key, val] of props) {
target[key] = val;
}
return target;
};
var defaultsDynamic = /* @__PURE__ */ _export_sfc(_sfc_main, [__FILE__]);
export { defaultsDynamic as default };
"
`;

exports[`fixtures > tests/fixtures/defaults-static.vue 1`] = `
"import { defineComponent, openBlock, createElementBlock } from 'vue';
var _sfc_main = /* @__PURE__ */ defineComponent({
__name: \\"defaults\\",
__name: \\"defaults-static\\",
props: {
foo: { type: String, required: false, default: \\"foo\\" },
bar: { type: Number, required: false, get default() {
Expand All @@ -64,9 +95,9 @@ var _export_sfc = (sfc, props) => {
return target;
};
var defaults = /* @__PURE__ */ _export_sfc(_sfc_main, [__FILE__]);
var defaultsStatic = /* @__PURE__ */ _export_sfc(_sfc_main, [__FILE__]);
export { defaults as default };
export { defaultsStatic as default };
"
`;

Expand Down
12 changes: 12 additions & 0 deletions packages/better-define/tests/fixtures/defaults-dynamic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script setup lang="ts">
withDefaults(defineProps<{
foo?: string
}>(), {
['f' + 'oo']: 'foo'
})
</script>

<template>
<div />
</template>
8 changes: 5 additions & 3 deletions packages/common/src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ export function isStaticExpression(
case 'ArrayExpression': // [1, 2]
return (
!!array &&
node.elements.every((element) => element && isStaticExpression(element))
node.elements.every(
(element) => element && isStaticExpression(element, options)
)
)

case 'ObjectExpression': // { foo: 1 }
Expand All @@ -133,11 +135,11 @@ export function isStaticExpression(
prop.argument.type === 'ObjectExpression' &&
isStaticExpression(prop.argument, options)
)
} else if (!isStaticExpression(prop.key) && prop.computed) {
} else if (!isLiteralType(prop.key) && prop.computed) {
return false
} else if (
prop.type === 'ObjectProperty' &&
!isStaticExpression(prop.value)
!isStaticExpression(prop.value, options)
) {
return false
}
Expand Down
6 changes: 5 additions & 1 deletion playground/vue3/src/examples/better-define/child.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ withDefaults(
defineProps<
Props & {
union?: string | number
nonStaticValue?: string
}
>(),
{ union: 'defaultValue' }
{
...{ union: 'defaultValue' },
['non' + 'StaticValue']: 'defaultValue',
}
)
defineEmits<Emits>()
Expand Down
2 changes: 2 additions & 0 deletions playground/vue3/src/examples/better-define/index.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<script setup lang="ts">
import child from './child.vue'
import ReactivityTransform from './reactivity-transform.vue'
</script>

<template>
<child name="" msg="" :age="10" union="" />
<reactivity-transform />
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
const { foo = 'foo' } = defineProps<{
foo?: string
}>()
console.log(foo)
</script>

<template>
{{ foo }}
</template>

0 comments on commit b5fa188

Please sign in to comment.