restructure EventHandler
This commit is contained in:
parent
6578727c9c
commit
8dbd2c4696
@ -33,7 +33,7 @@ export class ItemFormat extends AbstractItem {
|
|||||||
* @param {ID} id
|
* @param {ID} id
|
||||||
* @param {AbstractItem | null} left
|
* @param {AbstractItem | null} left
|
||||||
* @param {AbstractItem | null} right
|
* @param {AbstractItem | null} right
|
||||||
* @param {AbstractType<any> parent
|
* @param {AbstractType<any>} parent
|
||||||
* @param {string | null} parentSub
|
* @param {string | null} parentSub
|
||||||
*/
|
*/
|
||||||
copy (id, left, right, parent, parentSub) {
|
copy (id, left, right, parent, parentSub) {
|
||||||
|
@ -34,7 +34,7 @@ export class ItemJSON extends AbstractItem {
|
|||||||
* @param {ID} id
|
* @param {ID} id
|
||||||
* @param {AbstractItem | null} left
|
* @param {AbstractItem | null} left
|
||||||
* @param {AbstractItem | null} right
|
* @param {AbstractItem | null} right
|
||||||
* @param {AbstractType<any> parent
|
* @param {AbstractType<any>} parent
|
||||||
* @param {string | null} parentSub
|
* @param {string | null} parentSub
|
||||||
*/
|
*/
|
||||||
copy (id, left, right, parent, parentSub) {
|
copy (id, left, right, parent, parentSub) {
|
||||||
|
@ -33,7 +33,7 @@ export class ItemString extends AbstractItem {
|
|||||||
* @param {ID} id
|
* @param {ID} id
|
||||||
* @param {AbstractItem | null} left
|
* @param {AbstractItem | null} left
|
||||||
* @param {AbstractItem | null} right
|
* @param {AbstractItem | null} right
|
||||||
* @param {AbstractType<any> parent
|
* @param {AbstractType<any>} parent
|
||||||
* @param {string | null} parentSub
|
* @param {string | null} parentSub
|
||||||
*/
|
*/
|
||||||
copy (id, left, right, parent, parentSub) {
|
copy (id, left, right, parent, parentSub) {
|
||||||
|
@ -67,7 +67,7 @@ export class ItemType extends AbstractItem {
|
|||||||
* @param {ID} id
|
* @param {ID} id
|
||||||
* @param {AbstractItem | null} left
|
* @param {AbstractItem | null} left
|
||||||
* @param {AbstractItem | null} right
|
* @param {AbstractItem | null} right
|
||||||
* @param {AbstractType<any> parent
|
* @param {AbstractType<any>} parent
|
||||||
* @param {string | null} parentSub
|
* @param {string | null} parentSub
|
||||||
* @return {AbstractItem} TODO, returns itemtype
|
* @return {AbstractItem} TODO, returns itemtype
|
||||||
*/
|
*/
|
||||||
@ -150,7 +150,7 @@ export class ItemTypeRef extends AbstractItemRef {
|
|||||||
super(decoder, id, info)
|
super(decoder, id, info)
|
||||||
const typeRef = decoding.readVarUint(decoder)
|
const typeRef = decoding.readVarUint(decoder)
|
||||||
/**
|
/**
|
||||||
* @type {AbstractType<any>
|
* @type {AbstractType<any>}
|
||||||
*/
|
*/
|
||||||
this.type = typeRefs[typeRef](decoder)
|
this.type = typeRefs[typeRef](decoder)
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||||
import { EventHandler } from '../utils/EventHandler.js'
|
import * as eventHandler from '../utils/EventHandler.js'
|
||||||
import { YEvent } from '../utils/YEvent.js'
|
import { YEvent } from '../utils/YEvent.js' // eslint-disable-line
|
||||||
import { AbstractItem } from '../structs/AbstractItem.js' // eslint-disable-line
|
import { AbstractItem } from '../structs/AbstractItem.js' // eslint-disable-line
|
||||||
import { ItemType } from '../structs/ItemType.js' // eslint-disable-line
|
import { ItemType } from '../structs/ItemType.js' // eslint-disable-line
|
||||||
import { Encoder } from 'lib0/encoding.js' // eslint-disable-line
|
import { Encoder } from 'lib0/encoding.js' // eslint-disable-line
|
||||||
@ -16,6 +16,7 @@ import { ItemBinary } from '../structs/ItemBinary.js'
|
|||||||
import { ID, createID } from '../utils/ID.js' // eslint-disable-line
|
import { ID, createID } from '../utils/ID.js' // eslint-disable-line
|
||||||
import { getItemCleanStart, getItemCleanEnd } from '../utils/StructStore.js'
|
import { getItemCleanStart, getItemCleanEnd } from '../utils/StructStore.js'
|
||||||
import * as iterator from 'lib0/iterator.js'
|
import * as iterator from 'lib0/iterator.js'
|
||||||
|
import * as error from 'lib0/error.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template EventType
|
* @template EventType
|
||||||
@ -43,8 +44,16 @@ export class AbstractType {
|
|||||||
*/
|
*/
|
||||||
this._y = null
|
this._y = null
|
||||||
this._length = 0
|
this._length = 0
|
||||||
this._eventHandler = new EventHandler()
|
/**
|
||||||
this._deepEventHandler = new EventHandler()
|
* Event handlers
|
||||||
|
* @type {eventHandler.EventHandler<EventType,Transaction>}
|
||||||
|
*/
|
||||||
|
this._eH = eventHandler.create()
|
||||||
|
/**
|
||||||
|
* Deep event handlers
|
||||||
|
* @type {eventHandler.EventHandler<Array<YEvent>,Transaction>}
|
||||||
|
*/
|
||||||
|
this._dEH = eventHandler.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,14 +98,16 @@ export class AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates YEvent and calls observers.
|
* Creates YEvent and calls _callEventHandler.
|
||||||
|
* Must be implemented by each type.
|
||||||
|
* @todo Rename to _createEvent
|
||||||
* @private
|
* @private
|
||||||
*
|
*
|
||||||
* @param {Transaction} transaction
|
* @param {Transaction} transaction
|
||||||
* @param {Set<null|string>} parentSubs Keys changed on this type. `null` if list was modified.
|
* @param {Set<null|string>} parentSubs Keys changed on this type. `null` if list was modified.
|
||||||
*/
|
*/
|
||||||
_callObserver (transaction, parentSubs) {
|
_callObserver (transaction, parentSubs) {
|
||||||
this._callEventHandler(transaction, new YEvent(this, transaction))
|
throw error.methodUnimplemented()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,8 +119,8 @@ export class AbstractType {
|
|||||||
* @param {any} event
|
* @param {any} event
|
||||||
*/
|
*/
|
||||||
_callEventHandler (transaction, event) {
|
_callEventHandler (transaction, event) {
|
||||||
|
eventHandler.callEventListeners(this._eH, [event, transaction])
|
||||||
const changedParentTypes = transaction.changedParentTypes
|
const changedParentTypes = transaction.changedParentTypes
|
||||||
this._eventHandler.callEventListeners(transaction, event)
|
|
||||||
/**
|
/**
|
||||||
* @type {AbstractType<EventType>}
|
* @type {AbstractType<EventType>}
|
||||||
*/
|
*/
|
||||||
@ -127,37 +138,37 @@ export class AbstractType {
|
|||||||
/**
|
/**
|
||||||
* Observe all events that are created on this type.
|
* Observe all events that are created on this type.
|
||||||
*
|
*
|
||||||
* @param {function(EventType):void} f Observer function
|
* @param {function(EventType, Transaction):void} f Observer function
|
||||||
*/
|
*/
|
||||||
observe (f) {
|
observe (f) {
|
||||||
this._eventHandler.addEventListener(f)
|
eventHandler.addEventListener(this._eH, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observe all events that are created by this type and its children.
|
* Observe all events that are created by this type and its children.
|
||||||
*
|
*
|
||||||
* @param {function(Array<YEvent>):void} f Observer function
|
* @param {function(Array<YEvent>,Transaction):void} f Observer function
|
||||||
*/
|
*/
|
||||||
observeDeep (f) {
|
observeDeep (f) {
|
||||||
this._deepEventHandler.addEventListener(f)
|
eventHandler.addEventListener(this._dEH, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister an observer function.
|
* Unregister an observer function.
|
||||||
*
|
*
|
||||||
* @param {Function} f Observer function
|
* @param {function(EventType,Transaction):void} f Observer function
|
||||||
*/
|
*/
|
||||||
unobserve (f) {
|
unobserve (f) {
|
||||||
this._eventHandler.removeEventListener(f)
|
eventHandler.removeEventListener(this._eH, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister an observer function.
|
* Unregister an observer function.
|
||||||
*
|
*
|
||||||
* @param {Function} f Observer function
|
* @param {function(Array<YEvent>,Transaction):void} f Observer function
|
||||||
*/
|
*/
|
||||||
unobserveDeep (f) {
|
unobserveDeep (f) {
|
||||||
this._deepEventHandler.removeEventListener(f)
|
eventHandler.removeEventListener(this._dEH, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,7 @@ import * as decoding from 'lib0/decoding.js'
|
|||||||
/**
|
/**
|
||||||
* You can manage binding to a custom type with YXmlHook.
|
* You can manage binding to a custom type with YXmlHook.
|
||||||
*
|
*
|
||||||
* @public
|
* @extends {YMap<any>}
|
||||||
*/
|
*/
|
||||||
export class YXmlHook extends YMap {
|
export class YXmlHook extends YMap {
|
||||||
/**
|
/**
|
||||||
|
@ -1,70 +1,66 @@
|
|||||||
/**
|
import { Transaction } from './Transaction.js' // eslint-disable-line
|
||||||
* @module utils
|
import { YEvent } from './YEvent.js' // eslint-disable-line
|
||||||
*/
|
import * as f from 'lib0/function.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General event handler implementation.
|
* General event handler implementation.
|
||||||
|
*
|
||||||
|
* @template ARG0, ARG1
|
||||||
*/
|
*/
|
||||||
export class EventHandler {
|
export class EventHandler {
|
||||||
constructor () {
|
constructor () {
|
||||||
this.eventListeners = []
|
/**
|
||||||
|
* @type {Array<function(ARG0, ARG1):void>}
|
||||||
|
*/
|
||||||
|
this.l = []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To prevent memory leaks, call this method when the eventListeners won't be
|
* @template ARG0,ARG1
|
||||||
* used anymore.
|
* @returns {EventHandler<ARG0,ARG1>}
|
||||||
*/
|
*/
|
||||||
destroy () {
|
export const create = () => new EventHandler()
|
||||||
this.eventListeners = null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event listener that is called when
|
* Adds an event listener that is called when
|
||||||
* {@link EventHandler#callEventListeners} is called.
|
* {@link EventHandler#callEventListeners} is called.
|
||||||
*
|
*
|
||||||
* @param {Function} f The event handler.
|
* @template ARG0,ARG1
|
||||||
|
* @param {EventHandler<ARG0,ARG1>} eventHandler
|
||||||
|
* @param {function(ARG0,ARG1):void} f The event handler.
|
||||||
*/
|
*/
|
||||||
addEventListener (f) {
|
export const addEventListener = (eventHandler, f) =>
|
||||||
this.eventListeners.push(f)
|
eventHandler.l.push(f)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an event listener.
|
* Removes an event listener.
|
||||||
*
|
*
|
||||||
* @param {Function} f The event handler that was added with
|
* @template ARG0,ARG1
|
||||||
|
* @param {EventHandler<ARG0,ARG1>} eventHandler
|
||||||
|
* @param {function(ARG0,ARG1):void} f The event handler that was added with
|
||||||
* {@link EventHandler#addEventListener}
|
* {@link EventHandler#addEventListener}
|
||||||
*/
|
*/
|
||||||
removeEventListener (f) {
|
export const removeEventListener = (eventHandler, f) => {
|
||||||
this.eventListeners = this.eventListeners.filter(g => f !== g)
|
eventHandler.l = eventHandler.l.filter(g => f !== g)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all event listeners.
|
* Removes all event listeners.
|
||||||
|
* @template ARG0,ARG1
|
||||||
|
* @param {EventHandler<ARG0,ARG1>} eventHandler
|
||||||
*/
|
*/
|
||||||
removeAllEventListeners () {
|
export const removeAllEventListeners = eventHandler => {
|
||||||
this.eventListeners = []
|
eventHandler.l.length = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call all event listeners that were added via
|
* Call all event listeners that were added via
|
||||||
* {@link EventHandler#addEventListener}.
|
* {@link EventHandler#addEventListener}.
|
||||||
*
|
*
|
||||||
* @param {Transaction} transaction The transaction object
|
* @template ARG0,ARG1
|
||||||
* @param {YEvent} event An event object that describes the change on a type.
|
* @param {EventHandler<ARG0,ARG1>} eventHandler
|
||||||
|
* @param {[ARG0,ARG1]} args
|
||||||
*/
|
*/
|
||||||
callEventListeners (transaction, event) {
|
export const callEventListeners = (eventHandler, args) =>
|
||||||
for (var i = 0; i < this.eventListeners.length; i++) {
|
f.callAll(eventHandler.l, args)
|
||||||
try {
|
|
||||||
const f = this.eventListeners[i]
|
|
||||||
f(event, transaction)
|
|
||||||
} catch (e) {
|
|
||||||
/*
|
|
||||||
Your observer threw an error. This error was caught so that Yjs
|
|
||||||
can ensure data consistency! In order to debug this error you
|
|
||||||
have to check "Pause On Caught Exceptions" in developer tools.
|
|
||||||
*/
|
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
import * as ID from './ID.js'
|
import * as ID from './ID.js'
|
||||||
import { isParentOf } from './isParentOf.js'
|
import { isParentOf } from './isParentOf.js'
|
||||||
|
@ -15,6 +15,7 @@ import { YText } from '../types/YText.js'
|
|||||||
import { YMap } from '../types/YMap.js'
|
import { YMap } from '../types/YMap.js'
|
||||||
import { YXmlFragment } from '../types/YXmlElement.js'
|
import { YXmlFragment } from '../types/YXmlElement.js'
|
||||||
import { YEvent } from './YEvent.js' // eslint-disable-line
|
import { YEvent } from './YEvent.js' // eslint-disable-line
|
||||||
|
import * as eventHandler from './EventHandler.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Yjs instance handles the state of shared data.
|
* A Yjs instance handles the state of shared data.
|
||||||
@ -74,9 +75,7 @@ export class Y extends Observable {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
f(this._transaction)
|
f(this._transaction)
|
||||||
} catch (e) {
|
} finally {
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
if (initialCall) {
|
if (initialCall) {
|
||||||
const transaction = this._transaction
|
const transaction = this._transaction
|
||||||
this._transaction = null
|
this._transaction = null
|
||||||
@ -97,9 +96,9 @@ export class Y extends Observable {
|
|||||||
.forEach(event => {
|
.forEach(event => {
|
||||||
event.currentTarget = type
|
event.currentTarget = type
|
||||||
})
|
})
|
||||||
// we don't have to check for events.length
|
// we don't need to check for events.length
|
||||||
// because there is no way events is empty..
|
// because we know it has at least one element
|
||||||
type._deepEventHandler.callEventListeners(transaction, events)
|
eventHandler.callEventListeners(type._dEH, [events, transaction])
|
||||||
})
|
})
|
||||||
// when all changes & events are processed, emit afterTransaction event
|
// when all changes & events are processed, emit afterTransaction event
|
||||||
this.emit('afterTransaction', [this, transaction])
|
this.emit('afterTransaction', [this, transaction])
|
||||||
@ -179,6 +178,7 @@ export class Y extends Observable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Define a shared data type.
|
* Define a shared data type.
|
||||||
*
|
*
|
||||||
|
@ -81,7 +81,7 @@ export class YEvent {
|
|||||||
* console.log(path) // might look like => [2, 'key1']
|
* console.log(path) // might look like => [2, 'key1']
|
||||||
* child === type.get(path[0]).get(path[1])
|
* child === type.get(path[0]).get(path[1])
|
||||||
*
|
*
|
||||||
* @param {AbstractType<any> parent
|
* @param {AbstractType<any>} parent
|
||||||
* @param {AbstractItem} child target
|
* @param {AbstractItem} child target
|
||||||
* @return {Array<string|number>} Path to the target
|
* @return {Array<string|number>} Path to the target
|
||||||
*/
|
*/
|
||||||
|
@ -76,13 +76,13 @@ export class AbsolutePosition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {AbstractType<any> type
|
* @param {AbstractType<any>} type
|
||||||
* @param {number} offset
|
* @param {number} offset
|
||||||
*/
|
*/
|
||||||
export const createAbsolutePosition = (type, offset) => new AbsolutePosition(type, offset)
|
export const createAbsolutePosition = (type, offset) => new AbsolutePosition(type, offset)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {AbstractType<any> type
|
* @param {AbstractType<any>} type
|
||||||
* @param {ID.ID|null} item
|
* @param {ID.ID|null} item
|
||||||
*/
|
*/
|
||||||
export const createRelativePosition = (type, item) => {
|
export const createRelativePosition = (type, item) => {
|
||||||
@ -99,7 +99,7 @@ export const createRelativePosition = (type, item) => {
|
|||||||
/**
|
/**
|
||||||
* Create a relativePosition based on a absolute position.
|
* Create a relativePosition based on a absolute position.
|
||||||
*
|
*
|
||||||
* @param {AbstractType<any> type The base type (e.g. YText or YArray).
|
* @param {AbstractType<any>} type The base type (e.g. YText or YArray).
|
||||||
* @param {number} offset The absolute position.
|
* @param {number} offset The absolute position.
|
||||||
* @return {RelativePosition}
|
* @return {RelativePosition}
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user