import { isDeleted, AbstractType, Transaction, AbstractStruct // eslint-disable-line } from '../internals.js' /** * YEvent describes the changes on a YType. */ export class YEvent { /** * @param {AbstractType} target The changed type. * @param {Transaction} transaction */ constructor (target, transaction) { /** * The type on which this event was created on. * @type {AbstractType} */ this.target = target /** * The current target on which the observe callback is called. * @type {AbstractType} */ this.currentTarget = target /** * The transaction that triggered this event. * @type {Transaction} */ this.transaction = transaction } /** * Computes the path from `y` to the changed type. * * The following property holds: * @example * let type = y * event.path.forEach(dir => { * type = type.get(dir) * }) * type === event.target // => true */ get path () { // @ts-ignore _item is defined because target is integrated return getPathTo(this.currentTarget, this.target) } /** * Check if a struct is deleted by this event. * * @param {AbstractStruct} struct * @return {boolean} */ deletes (struct) { return isDeleted(this.transaction.deleteSet, struct.id) } /** * Check if a struct is added by this event. * * @param {AbstractStruct} struct * @return {boolean} */ adds (struct) { return struct.id.clock >= (this.transaction.beforeState.get(struct.id.client) || 0) } } /** * Compute the path from this type to the specified target. * * @example * // `child` should be accessible via `type.get(path[0]).get(path[1])..` * const path = type.getPathTo(child) * // assuming `type instanceof YArray` * console.log(path) // might look like => [2, 'key1'] * child === type.get(path[0]).get(path[1]) * * @param {AbstractType} parent * @param {AbstractType} child target * @return {Array} Path to the target * * @private * @function */ const getPathTo = (parent, child) => { const path = [] while (child._item !== null && child !== parent) { if (child._item.parentSub !== null) { // parent is map-ish path.unshift(child._item.parentSub) } else { // parent is array-ish let i = 0 let c = child._item.parent._start while (c !== child._item && c !== null) { if (!c.deleted) { i++ } c = c.right } path.unshift(i) } child = child._item.parent } return path }