nl_tokens: Patch for objects
pl_tokens: function _compareMaps ( a , b , options ) { debug ( a , b ) ; let alength = a . size === undefined ? a . length : a . size ; let blength = b . size === undefined ? b . length : b . size ; if ( alength === 0 && blength === 0 ) return ops . NOP ; // ops.Map([...b]) and not just ops.Rpl(b) because if b is a map it's not good JSON. if ( alength === 0 || blength === 0 ) return new ops . Map ( [ ... b ] ) ; let patch = [ ] ; if ( ! options . sorted ) { a = Array . from ( a ) . sort ( ( a , b ) => utils . compare ( a , b , options ) ) ; b = Array . from ( b ) . sort ( ( a , b ) => utils . compare ( a , b , options ) ) ; } let ai = 1 , bi = 1 ; let ao = a [ 0 ] , bo = b [ 0 ] let element_options = options . getArrayElementOptions ( ) ; do { let comparison = utils . compare ( ao , bo , options ) ; debug ( "comparing items" , ao , bo , comparison ) ; if ( comparison < 0 ) { debug ( 'skip' ) ; ao = a [ ai ++ ] ; } else if ( comparison > 0 ) { debug ( 'insert' ) ; patch . push ( [ options . key ( bo ) , new ops . Ins ( options . value ( bo ) ) ] ) ; bo = b [ bi ++ ] ; } else { if ( options . value ( ao ) !== options . value ( bo ) ) { let element_patch = compare ( options . value ( ao ) , options . value ( bo ) , element_options ) if ( element_patch != ops . NOP ) patch . push ( [ options . key ( bo ) , element_patch ] ) ; } else debug ( 'skip2' ) ; ao = a [ ai ++ ] ; bo = b [ bi ++ ] ; } } while ( ai <= a . length && bi <= b . length ) ; while ( ai <= a . length ) { <mask> . push ( [ options . key ( ao ) , ops . DEL ] ) ; ao = a [ ai ++ ] ; } while ( bi <= b . length ) { patch . push ( [ options . key ( bo ) , new ops . Ins ( options . value ( bo ) ) ] ) ; bo = b [ bi ++ ] ; } return new ops . Map ( patch ) ; }