@@ -32,6 +32,7 @@ import {
3232 isLoroTreeSchema ,
3333 LoroListSchema ,
3434 LoroMapSchema ,
35+ LoroMapSchemaWithCatchall ,
3536 RootSchemaType ,
3637 SchemaType ,
3738 validateSchema ,
@@ -504,9 +505,18 @@ export class Mirror<S extends SchemaType> {
504505 if ( isContainer ( value ) ) {
505506 let nestedSchema : ContainerSchemaType | undefined ;
506507 if ( parentSchema && isLoroMapSchema ( parentSchema ) ) {
507- nestedSchema = parentSchema . definition [
508- key
509- ] as ContainerSchemaType ;
508+ const candidate = this . getSchemaForMapKey (
509+ parentSchema as
510+ | LoroMapSchema < Record < string , SchemaType > >
511+ | LoroMapSchemaWithCatchall <
512+ Record < string , SchemaType > ,
513+ SchemaType
514+ > ,
515+ key ,
516+ ) ;
517+ if ( candidate && isContainerSchema ( candidate ) ) {
518+ nestedSchema = candidate ;
519+ }
510520 }
511521 this . registerContainer ( value . id , nestedSchema ) ;
512522 }
@@ -1419,16 +1429,19 @@ export class Mirror<S extends SchemaType> {
14191429 if ( ! isObject ( value ) ) {
14201430 return ;
14211431 }
1432+ const mapSchema = schema as
1433+ | LoroMapSchema < Record < string , SchemaType > >
1434+ | LoroMapSchemaWithCatchall <
1435+ Record < string , SchemaType > ,
1436+ SchemaType
1437+ >
1438+ | undefined ;
14221439 for ( const [ key , val ] of Object . entries ( value ) ) {
14231440 // Skip injected CID field
14241441 if ( key === CID_KEY ) continue ;
1425- const fieldSchema = (
1426- schema as
1427- | LoroMapSchema < Record < string , SchemaType > >
1428- | undefined
1429- ) ?. definition [ key ] ;
1442+ const fieldSchema = this . getSchemaForMapKey ( mapSchema , key ) ;
14301443
1431- if ( isContainerSchema ( fieldSchema ) ) {
1444+ if ( fieldSchema && isContainerSchema ( fieldSchema ) ) {
14321445 const ct = schemaToContainerType ( fieldSchema ) ;
14331446 if ( ct && isValueOfContainerType ( ct , val ) ) {
14341447 this . insertContainerIntoMap ( map , fieldSchema , key , val ) ;
@@ -1660,8 +1673,14 @@ export class Mirror<S extends SchemaType> {
16601673 ) {
16611674 if ( key === CID_KEY ) return ; // Ignore CID in writes
16621675 // Check if this field should be a container according to schema
1663- if ( schema && schema . type === "loro-map" && schema . definition ) {
1664- const fieldSchema = schema . definition [ key ] ;
1676+ if ( schema && schema . type === "loro-map" ) {
1677+ const mapSchema = schema as
1678+ | LoroMapSchema < Record < string , SchemaType > >
1679+ | LoroMapSchemaWithCatchall <
1680+ Record < string , SchemaType > ,
1681+ SchemaType
1682+ > ;
1683+ const fieldSchema = this . getSchemaForMapKey ( mapSchema , key ) ;
16651684 if ( fieldSchema && fieldSchema . type === "ignore" ) {
16661685 // Skip ignore fields: they live only in mirrored state
16671686 return ;
@@ -1926,6 +1945,27 @@ export class Mirror<S extends SchemaType> {
19261945 } ) ;
19271946 }
19281947
1948+ private getSchemaForMapKey (
1949+ schema :
1950+ | LoroMapSchema < Record < string , SchemaType > >
1951+ | LoroMapSchemaWithCatchall < Record < string , SchemaType > , SchemaType >
1952+ | undefined ,
1953+ key : string ,
1954+ ) : SchemaType | undefined {
1955+ if ( ! schema ) return undefined ;
1956+ if ( Object . prototype . hasOwnProperty . call ( schema . definition , key ) ) {
1957+ return schema . definition [ key ] ;
1958+ }
1959+ const withCatchall = schema as LoroMapSchemaWithCatchall <
1960+ Record < string , SchemaType > ,
1961+ SchemaType
1962+ > & { catchallType ?: SchemaType } ;
1963+ if ( withCatchall . catchallType ) {
1964+ return withCatchall . catchallType ;
1965+ }
1966+ return undefined ;
1967+ }
1968+
19291969 private getContainerSchema (
19301970 containerId : ContainerID ,
19311971 ) : ContainerSchemaType | undefined {
@@ -1956,7 +1996,15 @@ export class Mirror<S extends SchemaType> {
19561996 }
19571997
19581998 if ( isLoroMapSchema ( containerSchema ) ) {
1959- return containerSchema . definition [ childKey ] ;
1999+ return this . getSchemaForMapKey (
2000+ containerSchema as
2001+ | LoroMapSchema < Record < string , SchemaType > >
2002+ | LoroMapSchemaWithCatchall <
2003+ Record < string , SchemaType > ,
2004+ SchemaType
2005+ > ,
2006+ String ( childKey ) ,
2007+ ) ;
19602008 } else if (
19612009 isLoroListSchema ( containerSchema ) ||
19622010 isLoroMovableListSchema ( containerSchema )
0 commit comments