import * as Y from "yjs" ; import { Atom , createAtom } from "../observableProvider" ; const arraysObserved = new WeakSet < Y . Array < any > > ( ) ; export function observeArray ( array ) { if ( arraysObserved . has ( array ) ) { return array ; } arraysObserved . add ( array ) ; let selfAtom ; const atoms = new Map < number , 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" , ( ) => { array . observe ( handler ) ; } , ( ) => { array . unobserve ( handler ) ; } ) ; } selfAtom . reportObserved ( ( array as any ) . _implicitObserver ) ; } function reportArrayElementAtom ( key ) { let atom = atoms . get ( key ) ; if ( ! atom ) { const handler = ( event ) => { atom ! . reportChanged ( ) ; } ; atom = createAtom ( key + "" , ( ) => { array . observe ( handler ) ; } , ( ) => { array . unobserve ( handler ) ; } ) ; atoms . set ( key , atom ) ; } atom . reportObserved ( ( array as any ) . _implicitObserver ) ; } const originalGet = array . get ; array . get = function ( key ) { if ( typeof key !== "number" ) { throw new Error ( "unexpected" ) ; } reportArrayElementAtom ( key ) ; const ret = Reflect . apply ( originalGet , this , arguments ) ; return ret ; } ; function patch ( method ) { const originalFunction = array [ method ] ; array [ method ] = function ( ) { reportSelfAtom ( ) ; const ret = Reflect . apply ( originalFunction , this , arguments ) ; return ret ; } ; } patch ( "forEach" ) ; patch ( "toJSON" ) ; patch ( "toArray" ) ; patch ( "slice" ) ; patch ( "map" ) ; return array ; }