@@ -38,7 +38,8 @@ import {
38
38
RestElement ,
39
39
TSInterfaceBody ,
40
40
AwaitExpression ,
41
- Program
41
+ Program ,
42
+ ObjectMethod
42
43
} from '@babel/types'
43
44
import { walk } from 'estree-walker'
44
45
import { RawSourceMap } from 'source-map'
@@ -242,7 +243,7 @@ export function compileScript(
242
243
let hasDefineEmitCall = false
243
244
let hasDefineExposeCall = false
244
245
let propsRuntimeDecl : Node | undefined
245
- let propsRuntimeDefaults : Node | undefined
246
+ let propsRuntimeDefaults : ObjectExpression | undefined
246
247
let propsTypeDecl : TSTypeLiteral | TSInterfaceBody | undefined
247
248
let propsTypeDeclRaw : Node | undefined
248
249
let propsIdentifier : string | undefined
@@ -384,7 +385,16 @@ export function compileScript(
384
385
node
385
386
)
386
387
}
387
- propsRuntimeDefaults = node . arguments [ 1 ]
388
+ propsRuntimeDefaults = node . arguments [ 1 ] as ObjectExpression
389
+ if (
390
+ ! propsRuntimeDefaults ||
391
+ propsRuntimeDefaults . type !== 'ObjectExpression'
392
+ ) {
393
+ error (
394
+ `The 2nd argument of ${ WITH_DEFAULTS } must be an object literal.` ,
395
+ propsRuntimeDefaults || node
396
+ )
397
+ }
388
398
} else {
389
399
error (
390
400
`${ WITH_DEFAULTS } ' first argument must be a ${ DEFINE_PROPS } call.` ,
@@ -513,38 +523,51 @@ export function compileScript(
513
523
)
514
524
}
515
525
516
- function genRuntimeProps ( props : Record < string , PropTypeData > ) {
517
- const keys = Object . keys ( props )
518
- if ( ! keys . length ) {
519
- return ``
520
- }
521
-
522
- // check defaults. If the default object is an object literal with only
523
- // static properties, we can directly generate more optimzied default
524
- // decalrations. Otherwise we will have to fallback to runtime merging.
525
- const hasStaticDefaults =
526
+ /**
527
+ * check defaults. If the default object is an object literal with only
528
+ * static properties, we can directly generate more optimzied default
529
+ * decalrations. Otherwise we will have to fallback to runtime merging.
530
+ */
531
+ function checkStaticDefaults ( ) {
532
+ return (
526
533
propsRuntimeDefaults &&
527
534
propsRuntimeDefaults . type === 'ObjectExpression' &&
528
535
propsRuntimeDefaults . properties . every (
529
- node => node . type === 'ObjectProperty' && ! node . computed
536
+ node =>
537
+ ( node . type === 'ObjectProperty' && ! node . computed ) ||
538
+ node . type === 'ObjectMethod'
530
539
)
540
+ )
541
+ }
531
542
543
+ function genRuntimeProps ( props : Record < string , PropTypeData > ) {
544
+ const keys = Object . keys ( props )
545
+ if ( ! keys . length ) {
546
+ return ``
547
+ }
548
+ const hasStaticDefaults = checkStaticDefaults ( )
549
+ const scriptSetupSource = scriptSetup ! . content
532
550
let propsDecls = `{
533
551
${ keys
534
552
. map ( key => {
535
553
let defaultString : string | undefined
536
554
if ( hasStaticDefaults ) {
537
- const prop = (
538
- propsRuntimeDefaults as ObjectExpression
539
- ) . properties . find (
555
+ const prop = propsRuntimeDefaults ! . properties . find (
540
556
( node : any ) => node . key . name === key
541
- ) as ObjectProperty
557
+ ) as ObjectProperty | ObjectMethod
542
558
if ( prop ) {
543
- // prop has corresponding static default value
544
- defaultString = `default: ${ source . slice (
545
- prop . value . start ! + startOffset ,
546
- prop . value . end ! + startOffset
547
- ) } `
559
+ if ( prop . type === 'ObjectProperty' ) {
560
+ // prop has corresponding static default value
561
+ defaultString = `default: ${ scriptSetupSource . slice (
562
+ prop . value . start ! ,
563
+ prop . value . end !
564
+ ) } `
565
+ } else {
566
+ defaultString = `default() ${ scriptSetupSource . slice (
567
+ prop . body . start ! ,
568
+ prop . body . end !
569
+ ) } `
570
+ }
548
571
}
549
572
}
550
573
@@ -572,6 +595,44 @@ export function compileScript(
572
595
return `\n props: ${ propsDecls } as unknown as undefined,`
573
596
}
574
597
598
+ function genSetupPropsType ( node : TSTypeLiteral | TSInterfaceBody ) {
599
+ const scriptSetupSource = scriptSetup ! . content
600
+ if ( checkStaticDefaults ( ) ) {
601
+ // if withDefaults() is used, we need to remove the optional flags
602
+ // on props that have default values
603
+ let res = `: { `
604
+ const members = node . type === 'TSTypeLiteral' ? node . members : node . body
605
+ for ( const m of members ) {
606
+ if (
607
+ ( m . type === 'TSPropertySignature' ||
608
+ m . type === 'TSMethodSignature' ) &&
609
+ m . typeAnnotation &&
610
+ m . key . type === 'Identifier'
611
+ ) {
612
+ if (
613
+ propsRuntimeDefaults ! . properties . some (
614
+ ( p : any ) => p . key . name === ( m . key as Identifier ) . name
615
+ )
616
+ ) {
617
+ res +=
618
+ m . key . name +
619
+ ( m . type === 'TSMethodSignature' ? '()' : '' ) +
620
+ scriptSetupSource . slice (
621
+ m . typeAnnotation . start ! ,
622
+ m . typeAnnotation . end !
623
+ ) +
624
+ ', '
625
+ } else {
626
+ res += scriptSetupSource . slice ( m . start ! , m . end ! ) + `, `
627
+ }
628
+ }
629
+ }
630
+ return ( res . length ? res . slice ( 0 , - 2 ) : res ) + ` }`
631
+ } else {
632
+ return `: ${ scriptSetupSource . slice ( node . start ! , node . end ! ) } `
633
+ }
634
+ }
635
+
575
636
// 1. process normal <script> first if it exists
576
637
let scriptAst
577
638
if ( script ) {
@@ -990,10 +1051,7 @@ export function compileScript(
990
1051
// 9. finalize setup() argument signature
991
1052
let args = `__props`
992
1053
if ( propsTypeDecl ) {
993
- args += `: ${ scriptSetup . content . slice (
994
- propsTypeDecl . start ! ,
995
- propsTypeDecl . end !
996
- ) } `
1054
+ args += genSetupPropsType ( propsTypeDecl )
997
1055
}
998
1056
// inject user assignment of props
999
1057
// we use a default __props so that template expressions referencing props
0 commit comments