@@ -969,14 +969,22 @@ export class StylePolicy {
969969
970970 asFullySynthesizedSpec ( ) {
971971 const extractBuildSpecs = ( specOrPolicy , submorphs ) => {
972+ if ( specOrPolicy . __alreadySynthesized__ ) return specOrPolicy ;
972973 if ( specOrPolicy . COMMAND === 'add' ) {
973974 specOrPolicy = specOrPolicy . props ;
974975 }
975976 if ( specOrPolicy . COMMAND === 'remove' ) return null ; // target is already removed so just ignore the command
976977 if ( specOrPolicy . isPolicy ) return specOrPolicy . asFullySynthesizedSpec ( ) ;
978+ if ( ! submorphs ) submorphs = specOrPolicy . submorphs || [ ] ;
977979 const modelClass = specOrPolicy . defaultViewModel || specOrPolicy . viewModelClass ;
978980 const modelParams = { ...specOrPolicy . viewModel } || { } ; // accumulate the derivation chain for the viewModel
979- const synthesized = this . synthesizeSubSpec ( specOrPolicy === this . spec ? null : specOrPolicy . name ) ;
981+ const virtualMorph = {
982+ env : { } ,
983+ width : specOrPolicy . width || specOrPolicy . extent ?. x || 10 ,
984+ height : specOrPolicy . height || specOrPolicy . extent ?. y || 10
985+ } ;
986+ // if the owner of this morph has a layout, the extent or width may be different
987+ const synthesized = this . synthesizeSubSpec ( specOrPolicy === this . spec ? null : specOrPolicy . name , virtualMorph , virtualMorph ) ;
980988 if ( specOrPolicy . __wasAddedToDerived__ ) synthesized . __wasAddedToDerived__ = true ;
981989 if ( specOrPolicy . name ) synthesized . name = specOrPolicy . name ;
982990 // remove the props that are equal to the default value
@@ -993,7 +1001,7 @@ export class StylePolicy {
9931001 return textOrAttr ;
9941002 } ) ;
9951003 }
996- if ( synthesized . layout ) synthesized . layout = synthesized . layout . copy ( ) ;
1004+
9971005 if ( submorphs . length > 0 ) {
9981006 let transformedSubmorphs = submorphs . filter ( spec => spec && ! spec . __before__ ) ;
9991007 for ( let spec of submorphs ) {
@@ -1007,16 +1015,40 @@ export class StylePolicy {
10071015 }
10081016 synthesized . submorphs = transformedSubmorphs ;
10091017 }
1018+
1019+ if ( synthesized . layout ) {
1020+ synthesized . layout = synthesized . layout . copy ( ) ;
1021+ synthesized . layout . estimateSubmorphExtents ( synthesized , extractBuildSpecs ) ; // should be done before the submorph specs are synthesized
1022+ // however for submorphs which themselves are resized by layouts, the extent information is not yet determined
1023+ // estimate the container extent
1024+ }
1025+
10101026 if ( modelClass ) synthesized . viewModel = new modelClass ( modelParams ) ;
10111027 else delete synthesized . viewModel ;
10121028
1029+ synthesized . __alreadySynthesized__ = true ;
1030+
10131031 if ( ! synthesized . isPolicy ) {
10141032 return sanitizeSpec ( synthesized ) ;
10151033 }
10161034
10171035 return synthesized ;
10181036 } ;
1019- const buildSpec = tree . mapTree ( this . spec , extractBuildSpecs , node => node . props ?. submorphs || node . submorphs ) ;
1037+ const extractedBuildSpecs = new WeakMap ( ) ;
1038+ const buildSpec = tree . mapTree ( this . spec , ( node , submorphs ) => {
1039+ node = extractedBuildSpecs . get ( node ) ;
1040+ if ( node . layout ) {
1041+ node . layout . estimateContainerExtent ( node , submorphs ) ; // should be done after submorph specs are synthesized
1042+ }
1043+ if ( submorphs . length > 0 ) node . submorphs = submorphs ;
1044+ return node ;
1045+ } , node => {
1046+ let submorphs = node . props ?. submorphs || node . submorphs || [ ] ;
1047+ const synthesized = extractBuildSpecs ( node , submorphs ) ;
1048+ extractedBuildSpecs . set ( node , synthesized ) ;
1049+ if ( node . isPolicy ) return [ ] ; // no need to traverse further
1050+ return synthesized . submorphs ;
1051+ } ) ;
10201052 const self = this ;
10211053 buildSpec . onLoad = function ( ) {
10221054 const policy = self ;
0 commit comments