@@ -510,6 +510,7 @@ export class Mirror<S extends SchemaType> {
510510 if ( ! container . isAttached ) return ;
511511
512512 const parentSchema = this . getContainerSchema ( container . id ) ;
513+ const parentLocalInfer = this . inferOptionsByContainerId . get ( container . id ) ;
513514
514515 try {
515516 if ( container . kind ( ) === "Map" ) {
@@ -541,6 +542,17 @@ export class Mirror<S extends SchemaType> {
541542 nestedSchema = candidate ;
542543 }
543544 }
545+ if (
546+ ! parentSchema &&
547+ ! nestedSchema &&
548+ parentLocalInfer &&
549+ ! this . inferOptionsByContainerId . has ( value . id )
550+ ) {
551+ this . inferOptionsByContainerId . set (
552+ value . id ,
553+ parentLocalInfer ,
554+ ) ;
555+ }
544556 this . registerContainer ( value . id , nestedSchema ) ;
545557 }
546558 }
@@ -573,6 +585,17 @@ export class Mirror<S extends SchemaType> {
573585 nestedSchema = itemSchema ;
574586 }
575587 }
588+ if (
589+ ! parentSchema &&
590+ ! nestedSchema &&
591+ parentLocalInfer &&
592+ ! this . inferOptionsByContainerId . has ( value . id )
593+ ) {
594+ this . inferOptionsByContainerId . set (
595+ value . id ,
596+ parentLocalInfer ,
597+ ) ;
598+ }
576599 this . registerContainer ( value . id , nestedSchema ) ;
577600 }
578601 }
@@ -588,6 +611,17 @@ export class Mirror<S extends SchemaType> {
588611 // Register the node.data map and its nested containers
589612 this . registerContainer ( node . data . id , nodeSchema ) ;
590613 }
614+ } else if ( ! parentSchema && parentLocalInfer ) {
615+ const nodes = tree . getNodes ( ) ;
616+ for ( const node of nodes ) {
617+ if ( ! this . inferOptionsByContainerId . has ( node . data . id ) ) {
618+ this . inferOptionsByContainerId . set (
619+ node . data . id ,
620+ parentLocalInfer ,
621+ ) ;
622+ }
623+ this . registerContainer ( node . data . id , undefined ) ;
624+ }
591625 }
592626 }
593627 } catch ( error ) {
@@ -671,6 +705,13 @@ export class Mirror<S extends SchemaType> {
671705 const diff = event . diff . diff ;
672706
673707 const schema = this . getContainerSchema ( event . target ) ;
708+ const itemSchema =
709+ schema && isListLikeSchema ( schema )
710+ ? schema . itemSchema
711+ : undefined ;
712+ const parentLocalInfer = this . inferOptionsByContainerId . get (
713+ event . target ,
714+ ) ;
674715
675716 for ( const change of diff ) {
676717 if ( ! change . insert ) continue ;
@@ -682,17 +723,35 @@ export class Mirror<S extends SchemaType> {
682723 | ContainerSchemaType
683724 | undefined ;
684725
685- if ( schema && isListLikeSchema ( schema ) ) {
686- containerSchema =
687- schema . itemSchema as ContainerSchemaType ;
726+ if ( itemSchema ?. type === "any" ) {
727+ this . inferOptionsByContainerId . set (
728+ container . id ,
729+ this . getInferOptionsForChild (
730+ event . target ,
731+ itemSchema ,
732+ ) ,
733+ ) ;
734+ } else if ( isContainerSchema ( itemSchema ) ) {
735+ containerSchema = itemSchema ;
736+ } else if (
737+ ! schema &&
738+ parentLocalInfer &&
739+ ! this . inferOptionsByContainerId . has ( container . id )
740+ ) {
741+ this . inferOptionsByContainerId . set (
742+ container . id ,
743+ parentLocalInfer ,
744+ ) ;
688745 }
689746
690- this . registerContainer (
691- container . id ,
692- containerSchema ,
693- ) ;
747+ this . registerContainer ( container . id , containerSchema ) ;
694748
695- if ( ! containerSchema ) {
749+ if (
750+ schema &&
751+ itemSchema &&
752+ itemSchema . type !== "any" &&
753+ ! containerSchema
754+ ) {
696755 console . warn (
697756 `Container schema not found for key in list ${ event . target } ` ,
698757 ) ;
@@ -702,16 +761,42 @@ export class Mirror<S extends SchemaType> {
702761 }
703762 } else if ( event . diff . type === "map" ) {
704763 const diff = event . diff . updated ;
764+ const parentSchema = this . getContainerSchema ( event . target ) ;
765+ const parentLocalInfer = this . inferOptionsByContainerId . get (
766+ event . target ,
767+ ) ;
705768
706769 for ( const [ key , change ] of Object . entries ( diff ) ) {
707770 const schema = this . getSchemaForChild ( event . target , key ) ;
708771 if ( isContainer ( change ) ) {
709772 const containerSchema = isContainerSchema ( schema )
710773 ? schema
711774 : undefined ;
775+ if ( schema ?. type === "any" ) {
776+ this . inferOptionsByContainerId . set (
777+ change . id ,
778+ this . getInferOptionsForChild (
779+ event . target ,
780+ schema ,
781+ ) ,
782+ ) ;
783+ } else if (
784+ ! parentSchema &&
785+ parentLocalInfer &&
786+ ! this . inferOptionsByContainerId . has ( change . id )
787+ ) {
788+ this . inferOptionsByContainerId . set (
789+ change . id ,
790+ parentLocalInfer ,
791+ ) ;
792+ }
712793 this . registerContainer ( change . id , containerSchema ) ;
713794
714- if ( ! containerSchema ) {
795+ if (
796+ parentSchema &&
797+ ! containerSchema &&
798+ schema ?. type !== "any"
799+ ) {
715800 console . warn (
716801 `Container schema not found for key ${ key } in map ${ event . target } ` ,
717802 ) ;
@@ -1048,36 +1133,36 @@ export class Mirror<S extends SchemaType> {
10481133 container . id ,
10491134 key ,
10501135 ) ;
1051- const infer =
1052- fieldSchema ?. type === "any"
1053- ? this . getInferOptionsForChild (
1054- container . id ,
1055- fieldSchema ,
1056- )
1057- : ! schema
1058- ? this . getInferOptionsForContainer ( container . id )
1059- : undefined ;
1060- const [ detachedContainer , _containerType ] =
1061- this . createContainerFromSchema (
1062- schema ,
1063- value ,
1064- infer ,
1065- ) ;
1066- const newContainer = list . setContainer (
1067- index ,
1068- detachedContainer ,
1069- ) ;
1070-
1071- if ( ! schema && infer ) {
1072- this . inferOptionsByContainerId . set (
1073- newContainer . id ,
1074- infer ,
1075- ) ;
1076- }
1077- this . registerContainer ( newContainer . id , schema ) ;
1078- this . initializeContainer ( newContainer , schema , value ) ;
1079- // Stamp $cid into pending state when replacing with a map container
1080- this . stampCid ( value , newContainer . id ) ;
1136+ const infer =
1137+ fieldSchema ?. type === "any"
1138+ ? this . getInferOptionsForChild (
1139+ container . id ,
1140+ fieldSchema ,
1141+ )
1142+ : ! schema
1143+ ? this . getInferOptionsForContainer ( container . id )
1144+ : undefined ;
1145+ const [ detachedContainer , _containerType ] =
1146+ this . createContainerFromSchema (
1147+ schema ,
1148+ value ,
1149+ infer ,
1150+ ) ;
1151+ const newContainer = list . setContainer (
1152+ index ,
1153+ detachedContainer ,
1154+ ) ;
1155+
1156+ if ( ! schema && infer ) {
1157+ this . inferOptionsByContainerId . set (
1158+ newContainer . id ,
1159+ infer ,
1160+ ) ;
1161+ }
1162+ this . registerContainer ( newContainer . id , schema ) ;
1163+ this . initializeContainer ( newContainer , schema , value ) ;
1164+ // Stamp $cid into pending state when replacing with a map container
1165+ this . stampCid ( value , newContainer . id ) ;
10811166 } else {
10821167 throw new Error ( ) ;
10831168 }
@@ -1440,18 +1525,18 @@ export class Mirror<S extends SchemaType> {
14401525 containerType = tryInferContainerType ( item , effectiveInfer ) ;
14411526 }
14421527
1443- if ( containerType && isValueOfContainerType ( containerType , item ) ) {
1444- const childInfer =
1445- containerSchema ? undefined : ( effectiveInfer || baseInfer ) ;
1446- this . insertContainerIntoList (
1447- list ,
1448- containerSchema ,
1449- index ,
1450- item ,
1451- childInfer ,
1452- ) ;
1453- return ;
1454- }
1528+ if ( containerType && isValueOfContainerType ( containerType , item ) ) {
1529+ const childInfer =
1530+ containerSchema ? undefined : ( effectiveInfer || baseInfer ) ;
1531+ this . insertContainerIntoList (
1532+ list ,
1533+ containerSchema ,
1534+ index ,
1535+ item ,
1536+ childInfer ,
1537+ ) ;
1538+ return ;
1539+ }
14551540
14561541 // Default to simple insert
14571542 list . insert ( index , item ) ;
@@ -1568,17 +1653,17 @@ export class Mirror<S extends SchemaType> {
15681653 fieldSchema ,
15691654 ) ;
15701655 const ct = tryInferContainerType ( val , infer ) ;
1571- if ( ct && isValueOfContainerType ( ct , val ) ) {
1572- this . insertContainerIntoMap (
1573- map ,
1574- undefined ,
1575- key ,
1576- val ,
1577- infer ,
1578- ) ;
1579- } else {
1580- map . set ( key , val ) ;
1581- }
1656+ if ( ct && isValueOfContainerType ( ct , val ) ) {
1657+ this . insertContainerIntoMap (
1658+ map ,
1659+ undefined ,
1660+ key ,
1661+ val ,
1662+ infer ,
1663+ ) ;
1664+ } else {
1665+ map . set ( key , val ) ;
1666+ }
15821667 continue ;
15831668 }
15841669
@@ -1601,12 +1686,18 @@ export class Mirror<S extends SchemaType> {
16011686 continue ;
16021687 }
16031688
1604- const ct = tryInferContainerType ( val , baseInfer ) ;
1605- if ( ct && isValueOfContainerType ( ct , val ) ) {
1606- this . insertContainerIntoMap ( map , undefined , key , val , baseInfer ) ;
1607- } else {
1608- map . set ( key , val ) ;
1609- }
1689+ const ct = tryInferContainerType ( val , baseInfer ) ;
1690+ if ( ct && isValueOfContainerType ( ct , val ) ) {
1691+ this . insertContainerIntoMap (
1692+ map ,
1693+ undefined ,
1694+ key ,
1695+ val ,
1696+ baseInfer ,
1697+ ) ;
1698+ } else {
1699+ map . set ( key , val ) ;
1700+ }
16101701 }
16111702 } else if ( kind === "List" || kind === "MovableList" ) {
16121703 const list = container as LoroList | LoroMovableList ;
@@ -1625,10 +1716,18 @@ export class Mirror<S extends SchemaType> {
16251716 const item = value [ i ] ;
16261717
16271718 if ( itemSchema ?. type === "any" ) {
1628- const infer = applySchemaToInferOptions ( itemSchema , baseInfer ) || baseInfer ;
1719+ const infer =
1720+ applySchemaToInferOptions ( itemSchema , baseInfer ) ||
1721+ baseInfer ;
16291722 const ct = tryInferContainerType ( item , infer ) ;
16301723 if ( ct && isValueOfContainerType ( ct , item ) ) {
1631- this . insertContainerIntoList ( list , undefined , i , item , infer ) ;
1724+ this . insertContainerIntoList (
1725+ list ,
1726+ undefined ,
1727+ i ,
1728+ item ,
1729+ infer ,
1730+ ) ;
16321731 } else {
16331732 list . insert ( i , item ) ;
16341733 }
@@ -1645,13 +1744,19 @@ export class Mirror<S extends SchemaType> {
16451744 continue ;
16461745 }
16471746
1648- if ( ! itemSchema ) {
1649- const ct = tryInferContainerType ( item , baseInfer ) ;
1650- if ( ct && isValueOfContainerType ( ct , item ) ) {
1651- this . insertContainerIntoList ( list , undefined , i , item , baseInfer ) ;
1652- } else {
1653- list . insert ( i , item ) ;
1654- }
1747+ if ( ! itemSchema ) {
1748+ const ct = tryInferContainerType ( item , baseInfer ) ;
1749+ if ( ct && isValueOfContainerType ( ct , item ) ) {
1750+ this . insertContainerIntoList (
1751+ list ,
1752+ undefined ,
1753+ i ,
1754+ item ,
1755+ baseInfer ,
1756+ ) ;
1757+ } else {
1758+ list . insert ( i , item ) ;
1759+ }
16551760 continue ;
16561761 }
16571762
@@ -1833,7 +1938,13 @@ export class Mirror<S extends SchemaType> {
18331938 const ct = tryInferContainerType ( val , infer ) ;
18341939 if ( ct && isValueOfContainerType ( ct , val ) ) {
18351940 // No child schema; insert with inferred container type
1836- this . insertContainerIntoMap ( map , undefined , key , val , infer ) ;
1941+ this . insertContainerIntoMap (
1942+ map ,
1943+ undefined ,
1944+ key ,
1945+ val ,
1946+ infer ,
1947+ ) ;
18371948 } else {
18381949 map . set ( key , val ) ;
18391950 }
0 commit comments