import { Atom , createAtom } from "../observableProvider" ; import * as Y from "yjs" ; const mapsObserved = new WeakSet < Y . Map < any > > ( ) ; export function observeMap ( map ) { if ( mapsObserved . has ( map ) ) { return map ; } mapsObserved . add ( map ) ; let selfAtom ; const atoms = new Map < string , Atom > ( ) ; function reportSelfAtom ( ) { if ( ! selfAtom ) { const handler = ( event ) => { if ( event . changes . added . size || event . changes . deleted . size || event . changes . keys . size || event . changes . delta . length ) { selfAtom ! . reportChanged ( ) ; } } ; selfAtom = createAtom ( "map" , ( ) => { map . observe ( handler ) ; } , ( ) => { map . unobserve ( handler ) ; } ) ; } selfAtom . reportObserved ( ( map as any ) . _implicitObserver ) ; } function reportMapKeyAtom ( key ) { let atom = atoms . get ( key ) ; if ( ! atom ) { const handler = ( event ) => { if ( event . keysChanged . has ( key ) ) { if ( event . changes . added . size || event . changes . deleted . size || event . changes . keys . size || event . changes . delta . length ) { atom ! . reportChanged ( ) ; } } } ; atom = createAtom ( key , ( ) => { map . observe ( handler ) ; } , ( ) => { map . unobserve ( handler ) ; } ) ; atoms . set ( key , atom ) ; } atom . reportObserved ( ( map as any ) . _implicitObserver ) ; } const originalGet = map . get ; map . get = function ( key ) { if ( typeof key !== "string" ) { throw new Error ( "unexpected" ) ; } reportMapKeyAtom ( key ) ; const ret = Reflect . apply ( originalGet , this , arguments ) ; return ret ; } ; function patch ( method ) { const originalFunction = map [ method ] ; map [ method ] = function ( ) { reportSelfAtom ( ) ; const ret = Reflect . apply ( originalFunction , this , arguments ) ; return ret ; } ; } patch ( "values" ) ; patch ( "entries" ) ; patch ( "keys" ) ; patch ( "forEach" ) ; patch ( "toJSON" ) ; return map ; }