prelim refactor commit
This commit is contained in:
237
src/types/AbstractType.js
Normal file
237
src/types/AbstractType.js
Normal file
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* @module structs
|
||||
*/
|
||||
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
import { EventHandler } from '../utils/EventHandler.js'
|
||||
import { YEvent } from '../utils/YEvent.js'
|
||||
import { AbstractItem } from '../structs/AbstractItem.js' // eslint-disable-line
|
||||
import { ItemType } from '../structs/ItemType.js' // eslint-disable-line
|
||||
import { Encoder } from 'lib0/encoding.js' // eslint-disable-line
|
||||
import { Transaction, nextID } from '../utils/Transaction.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Restructure children as if they were inserted one after another
|
||||
* @param {Transaction} transaction
|
||||
* @param {AbstractItem} start
|
||||
*/
|
||||
const integrateChildren = (transaction, start) => {
|
||||
let right
|
||||
while (true) {
|
||||
right = start.right
|
||||
start.id = nextID(transaction)
|
||||
start.right = null
|
||||
start.rightOrigin = null
|
||||
start.origin = start.left
|
||||
start.integrate(transaction)
|
||||
if (right !== null) {
|
||||
start = right
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract Yjs Type class
|
||||
*/
|
||||
export class AbstractType {
|
||||
constructor () {
|
||||
/**
|
||||
* @type {ItemType|null}
|
||||
*/
|
||||
this._item = null
|
||||
/**
|
||||
* @private
|
||||
* @type {Map<string,AbstractItem>}
|
||||
*/
|
||||
this._map = new Map()
|
||||
/**
|
||||
* @private
|
||||
* @type {AbstractItem|null}
|
||||
*/
|
||||
this._start = null
|
||||
/**
|
||||
* @private
|
||||
* @type {Y|null}
|
||||
*/
|
||||
this._y = null
|
||||
this._length = 0
|
||||
this._eventHandler = new EventHandler()
|
||||
this._deepEventHandler = new EventHandler()
|
||||
}
|
||||
|
||||
/**
|
||||
* Integrate this type into the Yjs instance.
|
||||
*
|
||||
* * Save this struct in the os
|
||||
* * This type is sent to other client
|
||||
* * Observer functions are fired
|
||||
*
|
||||
* @param {Transaction} transaction The Yjs instance
|
||||
* @param {ItemType} item
|
||||
* @private
|
||||
*/
|
||||
_integrate (transaction, item) {
|
||||
this._y = transaction.y
|
||||
this._item = item
|
||||
// when integrating children we must make sure to
|
||||
// integrate start
|
||||
const start = this._start
|
||||
if (start !== null) {
|
||||
this._start = null
|
||||
integrateChildren(transaction, start)
|
||||
}
|
||||
// integrate map children_integrate
|
||||
const map = this._map
|
||||
this._map = new Map()
|
||||
map.forEach(t => {
|
||||
t.right = null
|
||||
t.rightOrigin = null
|
||||
integrateChildren(transaction, t)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {AbstractType}
|
||||
*/
|
||||
_copy () {
|
||||
throw new Error('unimplemented')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Encoder} encoder
|
||||
*/
|
||||
_write (encoder) {
|
||||
throw new Error('unimplemented')
|
||||
}
|
||||
|
||||
/**
|
||||
* The first non-deleted item
|
||||
*/
|
||||
get _first () {
|
||||
let n = this._start
|
||||
while (n !== null && n.deleted) {
|
||||
n = n.right
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates YArray Event and calls observers.
|
||||
* @private
|
||||
*/
|
||||
_callObserver (transaction, parentSubs, remote) {
|
||||
this._callEventHandler(transaction, new YEvent(this))
|
||||
}
|
||||
|
||||
/**
|
||||
* Call event listeners with an event. This will also add an event to all
|
||||
* parents (for `.observeDeep` handlers).
|
||||
* @private
|
||||
*/
|
||||
_callEventHandler (transaction, event) {
|
||||
const changedParentTypes = transaction.changedParentTypes
|
||||
this._eventHandler.callEventListeners(transaction, event)
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
let type = this
|
||||
while (type !== this._y) {
|
||||
let events = changedParentTypes.get(type)
|
||||
if (events === undefined) {
|
||||
events = []
|
||||
changedParentTypes.set(type, events)
|
||||
}
|
||||
events.push(event)
|
||||
type = type._parent
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to transact if the y instance is available.
|
||||
*
|
||||
* TODO: Currently event handlers are not thrown when a type is not registered
|
||||
* with a Yjs instance.
|
||||
* @private
|
||||
*/
|
||||
_transact (f) {
|
||||
const y = this._y
|
||||
if (y !== null) {
|
||||
y.transact(f)
|
||||
} else {
|
||||
f(y)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe all events that are created on this type.
|
||||
*
|
||||
* @param {Function} f Observer function
|
||||
*/
|
||||
observe (f) {
|
||||
this._eventHandler.addEventListener(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe all events that are created by this type and its children.
|
||||
*
|
||||
* @param {Function} f Observer function
|
||||
*/
|
||||
observeDeep (f) {
|
||||
this._deepEventHandler.addEventListener(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister an observer function.
|
||||
*
|
||||
* @param {Function} f Observer function
|
||||
*/
|
||||
unobserve (f) {
|
||||
this._eventHandler.removeEventListener(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister an observer function.
|
||||
*
|
||||
* @param {Function} f Observer function
|
||||
*/
|
||||
unobserveDeep (f) {
|
||||
this._deepEventHandler.removeEventListener(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {Object | Array | number | string}
|
||||
*/
|
||||
toJSON () {}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AbstractType} type
|
||||
* @return {Array<any>}
|
||||
*/
|
||||
export const typeToArray = type => {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a provided function on once on overy element of this YArray.
|
||||
*
|
||||
* @param {AbstractType} type
|
||||
* @param {function(any,number,AbstractType):void} f A function to execute on every element of this YArray.
|
||||
* @param {HistorySnapshot} [snapshot]
|
||||
*/
|
||||
export const typeForEach = (type, f, snapshot) => {
|
||||
let index = 0
|
||||
let n = type._start
|
||||
while (n !== null) {
|
||||
if (isVisible(n, snapshot) && n._countable) {
|
||||
const c = n.getContent()
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
f(c[i], index++, type)
|
||||
}
|
||||
}
|
||||
n = n._right
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,14 @@
|
||||
* @module types
|
||||
*/
|
||||
|
||||
import { Type } from '../structs/Type.js'
|
||||
import { AbstractType } from './AbstractType.js'
|
||||
import { ItemJSON } from '../structs/ItemJSON.js'
|
||||
import { ItemString } from '../structs/ItemString.js'
|
||||
import { ItemBinary } from '../structs/ItemBinary.js'
|
||||
import { stringifyItemID, logItemHelper } from '../structs/AbstractItem.js' // eslint-disable-line
|
||||
import { YEvent } from '../utils/YEvent.js'
|
||||
import { Transaction } from '../utils/Transaction.js' // eslint-disable-line
|
||||
import { Item, stringifyItemID, logItemHelper } from '../structs/Item.js' // eslint-disable-line
|
||||
import { ItemBinary } from '../structs/ItemBinary.js'
|
||||
import { isVisible } from '../utils/snapshot.js'
|
||||
import { isVisible, HistorySnapshot } from '../utils/snapshot.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Event that describes the changes on a YArray
|
||||
@@ -38,8 +38,8 @@ export class YArrayEvent extends YEvent {
|
||||
const target = this.target
|
||||
const transaction = this._transaction
|
||||
const addedElements = new Set()
|
||||
transaction.newTypes.forEach(type => {
|
||||
if (type._parent === target && !transaction.deletedStructs.has(type)) {
|
||||
transaction.added.forEach(type => {
|
||||
if (type._parent === target && !transaction.deleted.has(type)) {
|
||||
addedElements.add(type)
|
||||
}
|
||||
})
|
||||
@@ -58,8 +58,8 @@ export class YArrayEvent extends YEvent {
|
||||
const target = this.target
|
||||
const transaction = this._transaction
|
||||
const removedElements = new Set()
|
||||
transaction.deletedStructs.forEach(struct => {
|
||||
if (struct._parent === target && !transaction.newTypes.has(struct)) {
|
||||
transaction.deleted.forEach(struct => {
|
||||
if (struct._parent === target && !transaction.added.has(struct)) {
|
||||
removedElements.add(struct)
|
||||
}
|
||||
})
|
||||
@@ -72,7 +72,7 @@ export class YArrayEvent extends YEvent {
|
||||
/**
|
||||
* A shared Array implementation.
|
||||
*/
|
||||
export class YArray extends Type {
|
||||
export class YArray extends AbstractType {
|
||||
constructor () {
|
||||
super()
|
||||
this.length = 0
|
||||
@@ -128,7 +128,7 @@ export class YArray extends Type {
|
||||
*/
|
||||
toJSON () {
|
||||
return this.map(c => {
|
||||
if (c instanceof Type) {
|
||||
if (c instanceof AbstractType) {
|
||||
return c.toJSON()
|
||||
}
|
||||
return c
|
||||
@@ -140,7 +140,7 @@ export class YArray extends Type {
|
||||
* element of this YArray.
|
||||
*
|
||||
* @param {Function} f Function that produces an element of the new Array
|
||||
* @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
|
||||
* @param {HistorySnapshot} [snapshot]
|
||||
* @return {Array} A new array with each element being the result of the
|
||||
* callback function
|
||||
*/
|
||||
@@ -156,7 +156,7 @@ export class YArray extends Type {
|
||||
* Executes a provided function on once on overy element of this YArray.
|
||||
*
|
||||
* @param {Function} f A function to execute on every element of this YArray.
|
||||
* @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
|
||||
* @param {HistorySnapshot} [snapshot]
|
||||
*/
|
||||
forEach (f, snapshot) {
|
||||
let index = 0
|
||||
@@ -404,3 +404,5 @@ export class YArray extends Type {
|
||||
return logItemHelper('YArray', this, `start:${stringifyItemID(this._start)}"`)
|
||||
}
|
||||
}
|
||||
|
||||
export const readYArray = decoder => new YArray()
|
||||
@@ -2,12 +2,11 @@
|
||||
* @module types
|
||||
*/
|
||||
|
||||
import { Item, logItemHelper } from '../structs/Item.js'
|
||||
import { Type } from '../structs/Type.js'
|
||||
import { AbstractType } from './AbstractType.js'
|
||||
import { ItemJSON } from '../structs/ItemJSON.js'
|
||||
import { YEvent } from '../utils/YEvent.js'
|
||||
import { ItemBinary } from '../structs/ItemBinary.js'
|
||||
import { isVisible } from '../utils/snapshot.js'
|
||||
import { HistorySnapshot, isVisible } from '../utils/snapshot.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Event that describes the changes on a YMap.
|
||||
@@ -28,7 +27,7 @@ export class YMapEvent extends YEvent {
|
||||
/**
|
||||
* A shared Map implementation.
|
||||
*/
|
||||
export class YMap extends Type {
|
||||
export class YMap extends AbstractType {
|
||||
/**
|
||||
* Creates YMap Event and calls observers.
|
||||
*
|
||||
@@ -68,7 +67,7 @@ export class YMap extends Type {
|
||||
/**
|
||||
* Returns the keys for each element in the YMap Type.
|
||||
*
|
||||
* @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
|
||||
* @param {HistorySnapshot} [snapshot]
|
||||
* @return {Array}
|
||||
*/
|
||||
keys (snapshot) {
|
||||
@@ -156,7 +155,7 @@ export class YMap extends Type {
|
||||
* Returns a specified element from this YMap.
|
||||
*
|
||||
* @param {string} key The key of the element to return.
|
||||
* @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
|
||||
* @param {HistorySnapshot} [snapshot]
|
||||
*/
|
||||
get (key, snapshot) {
|
||||
let v = this._map.get(key)
|
||||
@@ -184,7 +183,7 @@ export class YMap extends Type {
|
||||
* Returns a boolean indicating whether the specified key exists or not.
|
||||
*
|
||||
* @param {string} key The key to test.
|
||||
* @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
|
||||
* @param {HistorySnapshot} [snapshot]
|
||||
*/
|
||||
has (key, snapshot) {
|
||||
let v = this._map.get(key)
|
||||
@@ -210,3 +209,5 @@ export class YMap extends Type {
|
||||
return logItemHelper('YMap', this, `mapSize:${this._map.size}`)
|
||||
}
|
||||
}
|
||||
|
||||
export const readYMap = decoder => new YMap()
|
||||
@@ -2,7 +2,7 @@
|
||||
* @module types
|
||||
*/
|
||||
|
||||
import { logItemHelper } from '../structs/Item.js'
|
||||
import { logItemHelper } from '../structs/AbstractItem.js/index.js'
|
||||
import { ItemEmbed } from '../structs/ItemEmbed.js'
|
||||
import { ItemString } from '../structs/ItemString.js'
|
||||
import { ItemFormat } from '../structs/ItemFormat.js'
|
||||
@@ -723,3 +723,5 @@ export class YText extends YArray {
|
||||
return logItemHelper('YText', this)
|
||||
}
|
||||
}
|
||||
|
||||
export const readYText = decoder => new YText()
|
||||
@@ -2,7 +2,7 @@
|
||||
* @module types
|
||||
*/
|
||||
|
||||
import { logItemHelper } from '../structs/Item.js'
|
||||
import { logItemHelper } from '../structs/AbstractItem.js/index.js'
|
||||
import { YMap } from './YMap.js'
|
||||
import * as encoding from 'lib0/encoding.js'
|
||||
import * as decoding from 'lib0/decoding.js'
|
||||
@@ -433,3 +433,6 @@ export class YXmlElement extends YXmlFragment {
|
||||
return dom
|
||||
}
|
||||
}
|
||||
|
||||
export const readYXmlElement = decoder => new YXmlElement(decoding.readVarString(decoder))
|
||||
export const readYXmlFragment = decoder => new YXmlFragment()
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { YEvent } from '../utils/YEvent.js'
|
||||
|
||||
import { Type } from '../structs/Type.js' // eslint-disable-line
|
||||
import { Type } from './AbstractType.js/index.js.js.js.js' // eslint-disable-line
|
||||
import { Transaction } from '../utils/Transaction.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
|
||||
@@ -114,3 +114,5 @@ export class YXmlHook extends YMap {
|
||||
super._integrate(y)
|
||||
}
|
||||
}
|
||||
|
||||
export const readYXmlHook = decoder => new YXmlHook()
|
||||
@@ -48,3 +48,5 @@ export class YXmlText extends YText {
|
||||
super._delete(y, createDelete, gcChildren)
|
||||
}
|
||||
}
|
||||
|
||||
export const readYXmlText = decoder => new YXmlText()
|
||||
|
||||
Reference in New Issue
Block a user