@@ -17,7 +17,12 @@ import {
17
17
def
18
18
} from '@vue/shared'
19
19
import { warn } from './warning'
20
- import { Data , ComponentInternalInstance } from './component'
20
+ import {
21
+ Data ,
22
+ ComponentInternalInstance ,
23
+ ComponentOptions ,
24
+ Component
25
+ } from './component'
21
26
import { isEmitListener } from './componentEmits'
22
27
import { InternalObjectKey } from './vnode'
23
28
@@ -96,7 +101,7 @@ type NormalizedProp =
96
101
97
102
// normalized value is a tuple of the actual normalized options
98
103
// and an array of prop keys that need value casting (booleans and defaults)
99
- type NormalizedPropsOptions = [ Record < string , NormalizedProp > , string [ ] ]
104
+ export type NormalizedPropsOptions = [ Record < string , NormalizedProp > , string [ ] ]
100
105
101
106
export function initProps (
102
107
instance : ComponentInternalInstance ,
@@ -108,17 +113,16 @@ export function initProps(
108
113
const attrs : Data = { }
109
114
def ( attrs , InternalObjectKey , 1 )
110
115
setFullProps ( instance , rawProps , props , attrs )
111
- const options = instance . type . props
112
116
// validation
113
- if ( __DEV__ && options && rawProps ) {
114
- validateProps ( props , options )
117
+ if ( __DEV__ ) {
118
+ validateProps ( props , instance . type )
115
119
}
116
120
117
121
if ( isStateful ) {
118
122
// stateful
119
123
instance . props = isSSR ? props : shallowReactive ( props )
120
124
} else {
121
- if ( ! options ) {
125
+ if ( ! instance . type . props ) {
122
126
// functional w/ optional props, props === attrs
123
127
instance . props = attrs
124
128
} else {
@@ -140,9 +144,8 @@ export function updateProps(
140
144
attrs,
141
145
vnode : { patchFlag }
142
146
} = instance
143
- const rawOptions = instance . type . props
144
147
const rawCurrentProps = toRaw ( props )
145
- const [ options ] = normalizePropsOptions ( rawOptions )
148
+ const [ options ] = normalizePropsOptions ( instance . type )
146
149
147
150
if ( ( optimized || patchFlag > 0 ) && ! ( patchFlag & PatchFlags . FULL_PROPS ) ) {
148
151
if ( patchFlag & PatchFlags . PROPS ) {
@@ -211,8 +214,8 @@ export function updateProps(
211
214
}
212
215
}
213
216
214
- if ( __DEV__ && rawOptions && rawProps ) {
215
- validateProps ( props , rawOptions )
217
+ if ( __DEV__ && rawProps ) {
218
+ validateProps ( props , instance . type )
216
219
}
217
220
}
218
221
@@ -222,9 +225,7 @@ function setFullProps(
222
225
props : Data ,
223
226
attrs : Data
224
227
) {
225
- const [ options , needCastKeys ] = normalizePropsOptions (
226
- instance . type . props
227
- )
228
+ const [ options , needCastKeys ] = normalizePropsOptions ( instance . type )
228
229
const emits = instance . type . emits
229
230
230
231
if ( rawProps ) {
@@ -292,16 +293,38 @@ function resolvePropValue(
292
293
}
293
294
294
295
export function normalizePropsOptions (
295
- raw : ComponentPropsOptions | undefined
296
+ comp : Component
296
297
) : NormalizedPropsOptions | [ ] {
297
- if ( ! raw ) {
298
- return EMPTY_ARR as any
299
- }
300
- if ( ( raw as any ) . _n ) {
301
- return ( raw as any ) . _n
298
+ if ( comp . __props ) {
299
+ return comp . __props
302
300
}
301
+
302
+ const raw = comp . props
303
303
const normalized : NormalizedPropsOptions [ 0 ] = { }
304
304
const needCastKeys : NormalizedPropsOptions [ 1 ] = [ ]
305
+
306
+ // apply mixin/extends props
307
+ let hasExtends = false
308
+ if ( __FEATURE_OPTIONS__ && ! isFunction ( comp ) ) {
309
+ const extendProps = ( raw : ComponentOptions ) => {
310
+ const [ props , keys ] = normalizePropsOptions ( raw )
311
+ Object . assign ( normalized , props )
312
+ if ( keys ) needCastKeys . push ( ...keys )
313
+ }
314
+ if ( comp . extends ) {
315
+ hasExtends = true
316
+ extendProps ( comp . extends )
317
+ }
318
+ if ( comp . mixins ) {
319
+ hasExtends = true
320
+ comp . mixins . forEach ( extendProps )
321
+ }
322
+ }
323
+
324
+ if ( ! raw && ! hasExtends ) {
325
+ return ( comp . __props = EMPTY_ARR )
326
+ }
327
+
305
328
if ( isArray ( raw ) ) {
306
329
for ( let i = 0 ; i < raw . length ; i ++ ) {
307
330
if ( __DEV__ && ! isString ( raw [ i ] ) ) {
@@ -312,7 +335,7 @@ export function normalizePropsOptions(
312
335
normalized [ normalizedKey ] = EMPTY_OBJ
313
336
}
314
337
}
315
- } else {
338
+ } else if ( raw ) {
316
339
if ( __DEV__ && ! isObject ( raw ) ) {
317
340
warn ( `invalid props options` , raw )
318
341
}
@@ -337,7 +360,7 @@ export function normalizePropsOptions(
337
360
}
338
361
}
339
362
const normalizedEntry : NormalizedPropsOptions = [ normalized , needCastKeys ]
340
- def ( raw , '_n' , normalizedEntry )
363
+ comp . __props = normalizedEntry
341
364
return normalizedEntry
342
365
}
343
366
@@ -368,16 +391,22 @@ function getTypeIndex(
368
391
return - 1
369
392
}
370
393
371
- function validateProps ( props : Data , rawOptions : ComponentPropsOptions ) {
394
+ /**
395
+ * dev only
396
+ */
397
+ function validateProps ( props : Data , comp : Component ) {
372
398
const rawValues = toRaw ( props )
373
- const options = normalizePropsOptions ( rawOptions ) [ 0 ]
399
+ const options = normalizePropsOptions ( comp ) [ 0 ]
374
400
for ( const key in options ) {
375
401
let opt = options [ key ]
376
402
if ( opt == null ) continue
377
403
validateProp ( key , rawValues [ key ] , opt , ! hasOwn ( rawValues , key ) )
378
404
}
379
405
}
380
406
407
+ /**
408
+ * dev only
409
+ */
381
410
function validatePropName ( key : string ) {
382
411
if ( key [ 0 ] !== '$' ) {
383
412
return true
@@ -387,6 +416,9 @@ function validatePropName(key: string) {
387
416
return false
388
417
}
389
418
419
+ /**
420
+ * dev only
421
+ */
390
422
function validateProp (
391
423
name : string ,
392
424
value : unknown ,
@@ -434,6 +466,9 @@ type AssertionResult = {
434
466
expectedType : string
435
467
}
436
468
469
+ /**
470
+ * dev only
471
+ */
437
472
function assertType ( value : unknown , type : PropConstructor ) : AssertionResult {
438
473
let valid
439
474
const expectedType = getType ( type )
@@ -457,6 +492,9 @@ function assertType(value: unknown, type: PropConstructor): AssertionResult {
457
492
}
458
493
}
459
494
495
+ /**
496
+ * dev only
497
+ */
460
498
function getInvalidTypeMessage (
461
499
name : string ,
462
500
value : unknown ,
@@ -485,6 +523,9 @@ function getInvalidTypeMessage(
485
523
return message
486
524
}
487
525
526
+ /**
527
+ * dev only
528
+ */
488
529
function styleValue ( value : unknown , type : string ) : string {
489
530
if ( type === 'String' ) {
490
531
return `"${ value } "`
@@ -495,11 +536,17 @@ function styleValue(value: unknown, type: string): string {
495
536
}
496
537
}
497
538
539
+ /**
540
+ * dev only
541
+ */
498
542
function isExplicable ( type : string ) : boolean {
499
543
const explicitTypes = [ 'string' , 'number' , 'boolean' ]
500
544
return explicitTypes . some ( elem => type . toLowerCase ( ) === elem )
501
545
}
502
546
547
+ /**
548
+ * dev only
549
+ */
503
550
function isBoolean ( ...args : string [ ] ) : boolean {
504
551
return args . some ( elem => elem . toLowerCase ( ) === 'boolean' )
505
552
}
0 commit comments