@@ -230,7 +230,7 @@ module.exports = {
230230 }
231231
232232 /**
233- * @param {* } node
233+ * @param {Expression } node
234234 * @param {ComponentObjectProp | ComponentTypeProp | ComponentInferTypeProp } prop
235235 * @param {Iterable<string> } expectedTypeNames
236236 */
@@ -249,17 +249,22 @@ module.exports = {
249249 } )
250250 }
251251
252+ /**
253+ * @typedef {object } DefaultDefine
254+ * @property {Expression } expression
255+ * @property {'assignment'|'withDefaults'|'defaultProperty' } src
256+ */
252257 /**
253258 * @param {(ComponentObjectProp | ComponentTypeProp | ComponentInferTypeProp)[] } props
254- * @param {(propName: string) => Expression[] } otherDefaultProvider
259+ * @param {(propName: string) => Iterable<DefaultDefine> } otherDefaultProvider
255260 */
256261 function processPropDefs ( props , otherDefaultProvider ) {
257262 /** @type {PropDefaultFunctionContext[] } */
258263 const propContexts = [ ]
259264 for ( const prop of props ) {
260265 let typeList
261- /** @type {Expression [] } */
262- const defExprList = [ ]
266+ /** @type {DefaultDefine [] } */
267+ const defaultList = [ ]
263268 if ( prop . type === 'object' ) {
264269 if ( prop . value . type === 'ObjectExpression' ) {
265270 const type = getPropertyNode ( prop . value , 'type' )
@@ -268,36 +273,44 @@ module.exports = {
268273 typeList = getTypes ( type . value )
269274
270275 const def = getPropertyNode ( prop . value , 'default' )
271- if ( ! def ) continue
272-
273- defExprList . push ( def . value )
276+ if ( def ) {
277+ defaultList . push ( {
278+ src : 'defaultProperty' ,
279+ expression : def . value
280+ } )
281+ }
274282 } else {
275283 typeList = getTypes ( prop . value )
276284 }
277285 } else {
278286 typeList = prop . types
279287 }
280288 if ( prop . propName != null ) {
281- defExprList . push ( ...otherDefaultProvider ( prop . propName ) )
289+ defaultList . push ( ...otherDefaultProvider ( prop . propName ) )
282290 }
283291
284- if ( defExprList . length === 0 ) continue
292+ if ( defaultList . length === 0 ) continue
285293
286294 const typeNames = new Set (
287295 typeList . filter ( ( item ) => NATIVE_TYPES . has ( item ) )
288296 )
289297 // There is no native types detected
290298 if ( typeNames . size === 0 ) continue
291299
292- for ( const defExpr of defExprList ) {
293- const defType = getValueType ( defExpr )
300+ for ( const defaultDef of defaultList ) {
301+ const defType = getValueType ( defaultDef . expression )
294302
295303 if ( ! defType ) continue
296304
297305 if ( defType . function ) {
298306 if ( typeNames . has ( 'Function' ) ) {
299307 continue
300308 }
309+ if ( defaultDef . src === 'assignment' ) {
310+ // Factory functions cannot be used in default definitions with initial value assignments.
311+ report ( defaultDef . expression , prop , typeNames )
312+ continue
313+ }
301314 if ( defType . expression ) {
302315 if ( ! defType . returnType || typeNames . has ( defType . returnType ) ) {
303316 continue
@@ -311,18 +324,23 @@ module.exports = {
311324 } )
312325 }
313326 } else {
314- if (
315- typeNames . has ( defType . type ) &&
316- ! FUNCTION_VALUE_TYPES . has ( defType . type )
317- ) {
318- continue
327+ if ( typeNames . has ( defType . type ) ) {
328+ if ( defaultDef . src === 'assignment' ) {
329+ continue
330+ }
331+ if ( ! FUNCTION_VALUE_TYPES . has ( defType . type ) ) {
332+ // For Array and Object, defaults must be defined in the factory function.
333+ continue
334+ }
319335 }
320336 report (
321- defExpr ,
337+ defaultDef . expression ,
322338 prop ,
323- [ ...typeNames ] . map ( ( type ) =>
324- FUNCTION_VALUE_TYPES . has ( type ) ? 'Function' : type
325- )
339+ defaultDef . src === 'assignment'
340+ ? typeNames
341+ : [ ...typeNames ] . map ( ( type ) =>
342+ FUNCTION_VALUE_TYPES . has ( type ) ? 'Function' : type
343+ )
326344 )
327345 }
328346 }
@@ -425,12 +443,19 @@ module.exports = {
425443 utils . getWithDefaultsPropExpressions ( node )
426444 const defaultsByAssignmentPatterns =
427445 utils . getDefaultPropExpressionsForPropsDestructure ( node )
428- const propContexts = processPropDefs ( props , ( propName ) =>
429- [
430- defaultsByWithDefaults [ propName ] ,
431- defaultsByAssignmentPatterns [ propName ] ?. expression
432- ] . filter ( utils . isDef )
433- )
446+ const propContexts = processPropDefs ( props , function * ( propName ) {
447+ const withDefaults = defaultsByWithDefaults [ propName ]
448+ if ( withDefaults ) {
449+ yield { src : 'withDefaults' , expression : withDefaults }
450+ }
451+ const assignmentPattern = defaultsByAssignmentPatterns [ propName ]
452+ if ( assignmentPattern ) {
453+ yield {
454+ src : 'assignment' ,
455+ expression : assignmentPattern . expression
456+ }
457+ }
458+ } )
434459 scriptSetupPropsContexts . push ( { node, props : propContexts } )
435460 } ,
436461 /**
@@ -450,7 +475,21 @@ module.exports = {
450475 }
451476 } ,
452477 onDefinePropsExit ( ) {
453- scriptSetupPropsContexts . pop ( )
478+ const data = scriptSetupPropsContexts . pop ( )
479+ if ( ! data ) {
480+ return
481+ }
482+ for ( const {
483+ prop,
484+ types : typeNames ,
485+ default : defType
486+ } of data . props ) {
487+ for ( const returnType of defType . returnTypes ) {
488+ if ( typeNames . has ( returnType . type ) ) continue
489+
490+ report ( returnType . node , prop , typeNames )
491+ }
492+ }
454493 }
455494 } )
456495 )
0 commit comments