fix #481 - calculate path correctly when parents are moved
This commit is contained in:
		
							parent
							
								
									7ced59c847
								
							
						
					
					
						commit
						5b16071380
					
				| @ -8,6 +8,7 @@ import { | |||||||
| import * as set from 'lib0/set' | import * as set from 'lib0/set' | ||||||
| import * as array from 'lib0/array' | import * as array from 'lib0/array' | ||||||
| import { addsStruct } from './Transaction.js' | import { addsStruct } from './Transaction.js' | ||||||
|  | import { ListCursor } from './ListCursor.js' | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * YEvent describes the changes on a YType. |  * YEvent describes the changes on a YType. | ||||||
| @ -62,7 +63,7 @@ export class YEvent { | |||||||
|    */ |    */ | ||||||
|   get path () { |   get path () { | ||||||
|     // @ts-ignore _item is defined because target is integrated
 |     // @ts-ignore _item is defined because target is integrated
 | ||||||
|     return getPathTo(this.currentTarget, this.target) |     return getPathTo(this.currentTarget, this.target, this.transaction) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @ -297,12 +298,13 @@ export class YEvent { | |||||||
|  * |  * | ||||||
|  * @param {AbstractType<any>} parent |  * @param {AbstractType<any>} parent | ||||||
|  * @param {AbstractType<any>} child target |  * @param {AbstractType<any>} child target | ||||||
|  |  * @param {Transaction} tr | ||||||
|  * @return {Array<string|number>} Path to the target |  * @return {Array<string|number>} Path to the target | ||||||
|  * |  * | ||||||
|  * @private |  * @private | ||||||
|  * @function |  * @function | ||||||
|  */ |  */ | ||||||
| const getPathTo = (parent, child) => { | const getPathTo = (parent, child, tr) => { | ||||||
|   const path = [] |   const path = [] | ||||||
|   while (child._item !== null && child !== parent) { |   while (child._item !== null && child !== parent) { | ||||||
|     if (child._item.parentSub !== null) { |     if (child._item.parentSub !== null) { | ||||||
| @ -310,15 +312,11 @@ const getPathTo = (parent, child) => { | |||||||
|       path.unshift(child._item.parentSub) |       path.unshift(child._item.parentSub) | ||||||
|     } else { |     } else { | ||||||
|       // parent is array-ish
 |       // parent is array-ish
 | ||||||
|       let i = 0 |       const c = new ListCursor(/** @type {AbstractType<any>} */ (child._item.parent)) | ||||||
|       let c = /** @type {AbstractType<any>} */ (child._item.parent)._start |       while (c.nextItem != null && !c.reachedEnd && c.nextItem !== child._item) { | ||||||
|       while (c !== child._item && c !== null) { |         c.forward(tr, (c.nextItem.countable && !c.nextItem.deleted) ? c.nextItem.length : 0, true) | ||||||
|         if (!c.deleted) { |  | ||||||
|           i++ |  | ||||||
|         } |  | ||||||
|         c = c.right |  | ||||||
|       } |       } | ||||||
|       path.unshift(i) |       path.unshift(c.index) | ||||||
|     } |     } | ||||||
|     child = /** @type {AbstractType<any>} */ (child._item.parent) |     child = /** @type {AbstractType<any>} */ (child._item.parent) | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -1,10 +1,56 @@ | |||||||
| import { init, compare, applyRandomTests, Doc, AbstractType, TestConnector, Item } from './testHelper.js' // eslint-disable-line
 | import { init, compare, applyRandomTests, Doc, Item } from './testHelper.js' // eslint-disable-line
 | ||||||
| 
 | 
 | ||||||
| import * as Y from '../src/index.js' | import * as Y from '../src/index.js' | ||||||
| import * as t from 'lib0/testing' | import * as t from 'lib0/testing' | ||||||
| import * as prng from 'lib0/prng' | import * as prng from 'lib0/prng' | ||||||
| import * as math from 'lib0/math' | import * as math from 'lib0/math' | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * path should be correct when moving item - see yjs#481 | ||||||
|  |  * | ||||||
|  |  * @param {t.TestCase} tc | ||||||
|  |  */ | ||||||
|  | export const testArrayMovePathIssue481 = tc => { | ||||||
|  |   const { users, testConnector, array0, array1 } = init(tc, { users: 2 }) | ||||||
|  |   array0.observeDeep(events => { | ||||||
|  |     events.forEach(event => { | ||||||
|  |       if (event.path.length > 0) { | ||||||
|  |         /** | ||||||
|  |          * @type {any} | ||||||
|  |          */ | ||||||
|  |         let target = event.currentTarget | ||||||
|  |         event.path.forEach(p => { | ||||||
|  |           target = target.get(p) | ||||||
|  |         }) | ||||||
|  |         t.assert(target === event.target) | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |   }) | ||||||
|  |   array0.push([ | ||||||
|  |     ['a', '1.1'], | ||||||
|  |     ['b', '2.2'], | ||||||
|  |     ['c', '3.1'], | ||||||
|  |     ['d', '4.1'], | ||||||
|  |     ['e', '5.1'] | ||||||
|  |   ].map(e => Y.Array.from(e))) | ||||||
|  |   testConnector.flushAllMessages() | ||||||
|  |   users[1].transact(() => { | ||||||
|  |     array1.get(1).insert(0, ['0']) | ||||||
|  |     array1.move(1, 0) | ||||||
|  |   }) | ||||||
|  |   testConnector.flushAllMessages() | ||||||
|  |   users[1].transact(() => { | ||||||
|  |     array1.get(3).insert(0, ['1']) | ||||||
|  |     array1.move(3, 4) | ||||||
|  |   }) | ||||||
|  |   testConnector.flushAllMessages() | ||||||
|  |   users[1].transact(() => { | ||||||
|  |     array1.get(2).insert(0, ['2']) | ||||||
|  |     array1.move(2, array1.length) | ||||||
|  |   }) | ||||||
|  |   testConnector.flushAllMessages() | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * foreach has correct index - see yjs#485 |  * foreach has correct index - see yjs#485 | ||||||
|  * |  * | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user