@y/y 14.0.0-19 → 14.0.0-21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/dist/src/index.d.ts +2 -1
- package/dist/src/internals.d.ts +2 -9
- package/dist/src/structs/ContentType.d.ts +6 -12
- package/dist/src/structs/ContentType.d.ts.map +1 -1
- package/dist/src/structs/Item.d.ts +5 -6
- package/dist/src/structs/Item.d.ts.map +1 -1
- package/dist/src/utils/AttributionManager.d.ts +16 -14
- package/dist/src/utils/AttributionManager.d.ts.map +1 -1
- package/dist/src/utils/Doc.d.ts +7 -70
- package/dist/src/utils/Doc.d.ts.map +1 -1
- package/dist/src/utils/ID.d.ts +2 -2
- package/dist/src/utils/ID.d.ts.map +1 -1
- package/dist/src/utils/IdMap.d.ts +22 -19
- package/dist/src/utils/IdMap.d.ts.map +1 -1
- package/dist/src/utils/IdSet.d.ts +6 -6
- package/dist/src/utils/IdSet.d.ts.map +1 -1
- package/dist/src/utils/RelativePosition.d.ts +8 -8
- package/dist/src/utils/RelativePosition.d.ts.map +1 -1
- package/dist/src/utils/Snapshot.d.ts +3 -3
- package/dist/src/utils/Snapshot.d.ts.map +1 -1
- package/dist/src/utils/Transaction.d.ts +9 -5
- package/dist/src/utils/Transaction.d.ts.map +1 -1
- package/dist/src/utils/UndoManager.d.ts +14 -12
- package/dist/src/utils/UndoManager.d.ts.map +1 -1
- package/dist/src/utils/UpdateDecoder.d.ts +8 -4
- package/dist/src/utils/UpdateDecoder.d.ts.map +1 -1
- package/dist/src/utils/UpdateEncoder.d.ts +2 -0
- package/dist/src/utils/UpdateEncoder.d.ts.map +1 -1
- package/dist/src/utils/YEvent.d.ts +21 -42
- package/dist/src/utils/YEvent.d.ts.map +1 -1
- package/dist/src/utils/encoding.d.ts +3 -3
- package/dist/src/utils/encoding.d.ts.map +1 -1
- package/dist/src/utils/isParentOf.d.ts +1 -1
- package/dist/src/utils/isParentOf.d.ts.map +1 -1
- package/dist/src/utils/logging.d.ts +2 -2
- package/dist/src/utils/logging.d.ts.map +1 -1
- package/dist/src/utils/meta.d.ts +71 -0
- package/dist/src/utils/meta.d.ts.map +1 -0
- package/dist/src/utils/ts.d.ts +4 -0
- package/dist/src/utils/ts.d.ts.map +1 -0
- package/dist/src/utils/updates.d.ts +11 -11
- package/dist/src/utils/updates.d.ts.map +1 -1
- package/dist/src/ytype.d.ts +498 -0
- package/dist/src/ytype.d.ts.map +1 -0
- package/dist/tests/IdMap.tests.d.ts.map +1 -1
- package/dist/tests/attribution.tests.d.ts +1 -0
- package/dist/tests/attribution.tests.d.ts.map +1 -1
- package/dist/tests/compatibility.tests.d.ts.map +1 -1
- package/dist/tests/doc.tests.d.ts.map +1 -1
- package/dist/tests/relativePositions.tests.d.ts +9 -9
- package/dist/tests/relativePositions.tests.d.ts.map +1 -1
- package/dist/tests/snapshot.tests.d.ts.map +1 -1
- package/dist/tests/testHelper.d.ts +28 -27
- package/dist/tests/testHelper.d.ts.map +1 -1
- package/dist/tests/undo-redo.tests.d.ts.map +1 -1
- package/dist/tests/updates.tests.d.ts +2 -1
- package/dist/tests/updates.tests.d.ts.map +1 -1
- package/dist/tests/y-array.tests.d.ts +0 -2
- package/dist/tests/y-array.tests.d.ts.map +1 -1
- package/dist/tests/y-map.tests.d.ts +0 -3
- package/dist/tests/y-map.tests.d.ts.map +1 -1
- package/dist/tests/y-text.tests.d.ts +1 -1
- package/dist/tests/y-text.tests.d.ts.map +1 -1
- package/dist/tests/y-xml.tests.d.ts +0 -1
- package/dist/tests/y-xml.tests.d.ts.map +1 -1
- package/package.json +16 -16
- package/src/index.js +156 -0
- package/src/internals.js +35 -0
- package/src/structs/AbstractStruct.js +59 -0
- package/src/structs/ContentAny.js +115 -0
- package/src/structs/ContentBinary.js +93 -0
- package/src/structs/ContentDeleted.js +101 -0
- package/src/structs/ContentDoc.js +141 -0
- package/src/structs/ContentEmbed.js +98 -0
- package/src/structs/ContentFormat.js +105 -0
- package/src/structs/ContentJSON.js +119 -0
- package/src/structs/ContentString.js +113 -0
- package/src/structs/ContentType.js +152 -0
- package/src/structs/GC.js +80 -0
- package/src/structs/Item.js +841 -0
- package/src/structs/Skip.js +75 -0
- package/src/utils/AttributionManager.js +653 -0
- package/src/utils/Doc.js +266 -0
- package/src/utils/EventHandler.js +87 -0
- package/src/utils/ID.js +89 -0
- package/src/utils/IdMap.js +673 -0
- package/src/utils/IdSet.js +825 -0
- package/src/utils/RelativePosition.js +352 -0
- package/src/utils/Snapshot.js +220 -0
- package/src/utils/StructSet.js +137 -0
- package/src/utils/StructStore.js +289 -0
- package/src/utils/Transaction.js +671 -0
- package/src/utils/UndoManager.js +406 -0
- package/src/utils/UpdateDecoder.js +285 -0
- package/src/utils/UpdateEncoder.js +327 -0
- package/src/utils/YEvent.js +189 -0
- package/src/utils/delta-helpers.js +54 -0
- package/src/utils/encoding.js +623 -0
- package/src/utils/isParentOf.js +21 -0
- package/src/utils/logging.js +21 -0
- package/src/utils/meta.js +190 -0
- package/src/utils/ts.js +3 -0
- package/src/utils/updates.js +802 -0
- package/src/ytype.js +1962 -0
- package/dist/Skip-CE05BUF8.js +0 -11875
- package/dist/Skip-CE05BUF8.js.map +0 -1
- package/dist/index-C21sDQ5u.js +0 -163
- package/dist/index-C21sDQ5u.js.map +0 -1
- package/dist/internals.js +0 -25
- package/dist/internals.js.map +0 -1
- package/dist/src/types/AbstractType.d.ts +0 -239
- package/dist/src/types/AbstractType.d.ts.map +0 -1
- package/dist/src/types/YArray.d.ts +0 -128
- package/dist/src/types/YArray.d.ts.map +0 -1
- package/dist/src/types/YMap.d.ts +0 -112
- package/dist/src/types/YMap.d.ts.map +0 -1
- package/dist/src/types/YText.d.ts +0 -216
- package/dist/src/types/YText.d.ts.map +0 -1
- package/dist/src/types/YXmlElement.d.ts +0 -106
- package/dist/src/types/YXmlElement.d.ts.map +0 -1
- package/dist/src/types/YXmlFragment.d.ts +0 -143
- package/dist/src/types/YXmlFragment.d.ts.map +0 -1
- package/dist/src/types/YXmlHook.d.ts +0 -32
- package/dist/src/types/YXmlHook.d.ts.map +0 -1
- package/dist/src/types/YXmlText.d.ts +0 -34
- package/dist/src/types/YXmlText.d.ts.map +0 -1
- package/dist/src/utils/AbstractConnector.d.ts +0 -20
- package/dist/src/utils/AbstractConnector.d.ts.map +0 -1
- package/dist/src/utils/types.d.ts +0 -7
- package/dist/src/utils/types.d.ts.map +0 -1
- package/dist/testHelper.js +0 -617
- package/dist/testHelper.js.map +0 -1
- package/dist/yjs.js +0 -26
- package/dist/yjs.js.map +0 -1
package/src/utils/Doc.js
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Y
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
StructStore,
|
|
7
|
+
transact,
|
|
8
|
+
applyUpdate,
|
|
9
|
+
ContentDoc, Item, Transaction, // eslint-disable-line
|
|
10
|
+
encodeStateAsUpdate
|
|
11
|
+
} from '../internals.js'
|
|
12
|
+
|
|
13
|
+
import { YType } from '../ytype.js'
|
|
14
|
+
import { ObservableV2 } from 'lib0/observable'
|
|
15
|
+
import * as random from 'lib0/random'
|
|
16
|
+
import * as map from 'lib0/map'
|
|
17
|
+
import * as array from 'lib0/array'
|
|
18
|
+
import * as promise from 'lib0/promise'
|
|
19
|
+
|
|
20
|
+
export const generateNewClientId = random.uint32
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {Object} DocOpts
|
|
24
|
+
* @property {boolean} [DocOpts.gc=true] Disable garbage collection (default: gc=true)
|
|
25
|
+
* @property {function(Item):boolean} [DocOpts.gcFilter] Will be called before an Item is garbage collected. Return false to keep the Item.
|
|
26
|
+
* @property {string} [DocOpts.guid] Define a globally unique identifier for this document
|
|
27
|
+
* @property {string | null} [DocOpts.collectionid] Associate this document with a collection. This only plays a role if your provider has a concept of collection.
|
|
28
|
+
* @property {any} [DocOpts.meta] Any kind of meta information you want to associate with this document. If this is a subdocument, remote peers will store the meta information as well.
|
|
29
|
+
* @property {boolean} [DocOpts.autoLoad] If a subdocument, automatically load document. If this is a subdocument, remote peers will load the document as well automatically.
|
|
30
|
+
* @property {boolean} [DocOpts.shouldLoad] Whether the document should be synced by the provider now. This is toggled to true when you call ydoc.load()
|
|
31
|
+
* @property {boolean} [DocOpts.isSuggestionDoc] Set to true if this document merely suggests
|
|
32
|
+
* changes. If this flag is not set in a suggestion document, automatic formatting changes will be
|
|
33
|
+
* displayed as suggestions, which might not be intended.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {Object} DocEvents
|
|
38
|
+
* @property {function(Doc):void} DocEvents.destroy
|
|
39
|
+
* @property {function(Doc):void} DocEvents.load
|
|
40
|
+
* @property {function(boolean, Doc):void} DocEvents.sync
|
|
41
|
+
* @property {function(Uint8Array<ArrayBuffer>, any, Doc, Transaction):void} DocEvents.update
|
|
42
|
+
* @property {function(Uint8Array<ArrayBuffer>, any, Doc, Transaction):void} DocEvents.updateV2
|
|
43
|
+
* @property {function(Doc):void} DocEvents.beforeAllTransactions
|
|
44
|
+
* @property {function(Transaction, Doc):void} DocEvents.beforeTransaction
|
|
45
|
+
* @property {function(Transaction, Doc):void} DocEvents.beforeObserverCalls
|
|
46
|
+
* @property {function(Transaction, Doc):void} DocEvents.afterTransaction
|
|
47
|
+
* @property {function(Transaction, Doc):void} DocEvents.afterTransactionCleanup
|
|
48
|
+
* @property {function(Doc, Array<Transaction>):void} DocEvents.afterAllTransactions
|
|
49
|
+
* @property {function({ loaded: Set<Doc>, added: Set<Doc>, removed: Set<Doc> }, Doc, Transaction):void} DocEvents.subdocs
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A Yjs instance handles the state of shared data.
|
|
54
|
+
* @extends ObservableV2<DocEvents>
|
|
55
|
+
*/
|
|
56
|
+
export class Doc extends ObservableV2 {
|
|
57
|
+
/**
|
|
58
|
+
* @param {DocOpts} opts configuration
|
|
59
|
+
*/
|
|
60
|
+
constructor ({ guid = random.uuidv4(), collectionid = null, gc = true, gcFilter = () => true, meta = null, autoLoad = false, shouldLoad = true, isSuggestionDoc = false } = {}) {
|
|
61
|
+
super()
|
|
62
|
+
this.gc = gc
|
|
63
|
+
this.gcFilter = gcFilter
|
|
64
|
+
this.clientID = generateNewClientId()
|
|
65
|
+
this.guid = guid
|
|
66
|
+
this.collectionid = collectionid
|
|
67
|
+
this.isSuggestionDoc = isSuggestionDoc
|
|
68
|
+
this.cleanupFormatting = !isSuggestionDoc
|
|
69
|
+
/**
|
|
70
|
+
* @type {Map<string, YType>}
|
|
71
|
+
*/
|
|
72
|
+
this.share = new Map()
|
|
73
|
+
this.store = new StructStore()
|
|
74
|
+
/**
|
|
75
|
+
* @type {Transaction | null}
|
|
76
|
+
*/
|
|
77
|
+
this._transaction = null
|
|
78
|
+
/**
|
|
79
|
+
* @type {Array<Transaction>}
|
|
80
|
+
*/
|
|
81
|
+
this._transactionCleanups = []
|
|
82
|
+
/**
|
|
83
|
+
* @type {Set<Doc>}
|
|
84
|
+
*/
|
|
85
|
+
this.subdocs = new Set()
|
|
86
|
+
/**
|
|
87
|
+
* If this document is a subdocument - a document integrated into another document - then _item is defined.
|
|
88
|
+
* @type {Item?}
|
|
89
|
+
*/
|
|
90
|
+
this._item = null
|
|
91
|
+
this.shouldLoad = shouldLoad
|
|
92
|
+
this.autoLoad = autoLoad
|
|
93
|
+
this.meta = meta
|
|
94
|
+
/**
|
|
95
|
+
* This is set to true when the persistence provider loaded the document from the database or when the `sync` event fires.
|
|
96
|
+
* Note that not all providers implement this feature. Provider authors are encouraged to fire the `load` event when the doc content is loaded from the database.
|
|
97
|
+
*
|
|
98
|
+
* @type {boolean}
|
|
99
|
+
*/
|
|
100
|
+
this.isLoaded = false
|
|
101
|
+
/**
|
|
102
|
+
* This is set to true when the connection provider has successfully synced with a backend.
|
|
103
|
+
* Note that when using peer-to-peer providers this event may not provide very useful.
|
|
104
|
+
* Also note that not all providers implement this feature. Provider authors are encouraged to fire
|
|
105
|
+
* the `sync` event when the doc has been synced (with `true` as a parameter) or if connection is
|
|
106
|
+
* lost (with false as a parameter).
|
|
107
|
+
*/
|
|
108
|
+
this.isSynced = false
|
|
109
|
+
this.isDestroyed = false
|
|
110
|
+
/**
|
|
111
|
+
* Promise that resolves once the document has been loaded from a persistence provider.
|
|
112
|
+
*/
|
|
113
|
+
this.whenLoaded = promise.create(resolve => {
|
|
114
|
+
this.on('load', () => {
|
|
115
|
+
this.isLoaded = true
|
|
116
|
+
resolve(this)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
const provideSyncedPromise = () => promise.create(resolve => {
|
|
120
|
+
/**
|
|
121
|
+
* @param {boolean} isSynced
|
|
122
|
+
*/
|
|
123
|
+
const eventHandler = (isSynced) => {
|
|
124
|
+
if (isSynced === undefined || isSynced === true) {
|
|
125
|
+
this.off('sync', eventHandler)
|
|
126
|
+
resolve()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
this.on('sync', eventHandler)
|
|
130
|
+
})
|
|
131
|
+
this.on('sync', isSynced => {
|
|
132
|
+
if (isSynced === false && this.isSynced) {
|
|
133
|
+
this.whenSynced = provideSyncedPromise()
|
|
134
|
+
}
|
|
135
|
+
this.isSynced = isSynced === undefined || isSynced === true
|
|
136
|
+
if (this.isSynced && !this.isLoaded) {
|
|
137
|
+
this.emit('load', [this])
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
/**
|
|
141
|
+
* Promise that resolves once the document has been synced with a backend.
|
|
142
|
+
* This promise is recreated when the connection is lost.
|
|
143
|
+
* Note the documentation about the `isSynced` property.
|
|
144
|
+
*/
|
|
145
|
+
this.whenSynced = provideSyncedPromise()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Notify the parent document that you request to load data into this subdocument (if it is a subdocument).
|
|
150
|
+
*
|
|
151
|
+
* `load()` might be used in the future to request any provider to load the most current data.
|
|
152
|
+
*
|
|
153
|
+
* It is safe to call `load()` multiple times.
|
|
154
|
+
*/
|
|
155
|
+
load () {
|
|
156
|
+
const item = this._item
|
|
157
|
+
if (item !== null && !this.shouldLoad) {
|
|
158
|
+
transact(/** @type {any} */ (item.parent).doc, transaction => {
|
|
159
|
+
transaction.subdocsLoaded.add(this)
|
|
160
|
+
}, null, true)
|
|
161
|
+
}
|
|
162
|
+
this.shouldLoad = true
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
getSubdocs () {
|
|
166
|
+
return this.subdocs
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
getSubdocGuids () {
|
|
170
|
+
return new Set(array.from(this.subdocs).map(doc => doc.guid))
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Changes that happen inside of a transaction are bundled. This means that
|
|
175
|
+
* the observer fires _after_ the transaction is finished and that all changes
|
|
176
|
+
* that happened inside of the transaction are sent as one message to the
|
|
177
|
+
* other peers.
|
|
178
|
+
*
|
|
179
|
+
* @template T
|
|
180
|
+
* @param {function(Transaction):T} f The function that should be executed as a transaction
|
|
181
|
+
* @param {any} [origin] Origin of who started the transaction. Will be stored on transaction.origin
|
|
182
|
+
* @return T
|
|
183
|
+
*
|
|
184
|
+
* @public
|
|
185
|
+
*/
|
|
186
|
+
transact (f, origin = null) {
|
|
187
|
+
return transact(this, f, origin)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Define a shared data type.
|
|
192
|
+
*
|
|
193
|
+
* Multiple calls of `ydoc.get(name)` yield the same result
|
|
194
|
+
* and do not overwrite each other. I.e.
|
|
195
|
+
* `ydoc.get(name) === ydoc.get(name)`
|
|
196
|
+
*
|
|
197
|
+
* After this method is called, the type is also available on `ydoc.share.get(name)`.
|
|
198
|
+
*
|
|
199
|
+
* @param {string} key
|
|
200
|
+
* @param {string?} name Type-name
|
|
201
|
+
*
|
|
202
|
+
* @return {YType}
|
|
203
|
+
*/
|
|
204
|
+
get (key = '', name = null) {
|
|
205
|
+
return map.setIfUndefined(this.share, key, () => {
|
|
206
|
+
const t = new YType(name)
|
|
207
|
+
t._integrate(this, null)
|
|
208
|
+
return t
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Converts the entire document into a js object, recursively traversing each yjs type
|
|
214
|
+
* Doesn't log types that have not been defined (using ydoc.getType(..)).
|
|
215
|
+
*
|
|
216
|
+
* @deprecated Do not use this method and rather call toJSON directly on the shared types.
|
|
217
|
+
*
|
|
218
|
+
* @return {Object<string, any>}
|
|
219
|
+
*/
|
|
220
|
+
toJSON () {
|
|
221
|
+
/**
|
|
222
|
+
* @type {Object<string, any>}
|
|
223
|
+
*/
|
|
224
|
+
const doc = {}
|
|
225
|
+
this.share.forEach((value, key) => {
|
|
226
|
+
doc[key] = value.toJSON()
|
|
227
|
+
})
|
|
228
|
+
return doc
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Emit `destroy` event and unregister all event handlers.
|
|
233
|
+
*/
|
|
234
|
+
destroy () {
|
|
235
|
+
this.isDestroyed = true
|
|
236
|
+
array.from(this.subdocs).forEach(subdoc => subdoc.destroy())
|
|
237
|
+
const item = this._item
|
|
238
|
+
if (item !== null) {
|
|
239
|
+
this._item = null
|
|
240
|
+
const content = /** @type {ContentDoc} */ (item.content)
|
|
241
|
+
content.doc = new Doc({ guid: this.guid, ...content.opts, shouldLoad: false })
|
|
242
|
+
content.doc._item = item
|
|
243
|
+
transact(/** @type {any} */ (item).parent.doc, transaction => {
|
|
244
|
+
const doc = content.doc
|
|
245
|
+
if (!item.deleted) {
|
|
246
|
+
transaction.subdocsAdded.add(doc)
|
|
247
|
+
}
|
|
248
|
+
transaction.subdocsRemoved.add(this)
|
|
249
|
+
}, null, true)
|
|
250
|
+
}
|
|
251
|
+
// @ts-ignore
|
|
252
|
+
this.emit('destroyed', [true]) // DEPRECATED!
|
|
253
|
+
this.emit('destroy', [this])
|
|
254
|
+
super.destroy()
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @param {Doc} ydoc
|
|
260
|
+
* @param {DocOpts} [opts]
|
|
261
|
+
*/
|
|
262
|
+
export const cloneDoc = (ydoc, opts) => {
|
|
263
|
+
const clone = new Doc(opts)
|
|
264
|
+
applyUpdate(clone, encodeStateAsUpdate(ydoc))
|
|
265
|
+
return clone
|
|
266
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as f from 'lib0/function'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* General event handler implementation.
|
|
5
|
+
*
|
|
6
|
+
* @template ARG0, ARG1
|
|
7
|
+
*
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
10
|
+
export class EventHandler {
|
|
11
|
+
constructor () {
|
|
12
|
+
/**
|
|
13
|
+
* @type {Array<function(ARG0, ARG1):void>}
|
|
14
|
+
*/
|
|
15
|
+
this.l = []
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @template ARG0,ARG1
|
|
21
|
+
* @returns {EventHandler<ARG0,ARG1>}
|
|
22
|
+
*
|
|
23
|
+
* @private
|
|
24
|
+
* @function
|
|
25
|
+
*/
|
|
26
|
+
export const createEventHandler = () => new EventHandler()
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Adds an event listener that is called when
|
|
30
|
+
* {@link EventHandler#callEventListeners} is called.
|
|
31
|
+
*
|
|
32
|
+
* @template ARG0,ARG1
|
|
33
|
+
* @param {EventHandler<ARG0,ARG1>} eventHandler
|
|
34
|
+
* @param {function(ARG0,ARG1):void} f The event handler.
|
|
35
|
+
*
|
|
36
|
+
* @private
|
|
37
|
+
* @function
|
|
38
|
+
*/
|
|
39
|
+
export const addEventHandlerListener = (eventHandler, f) =>
|
|
40
|
+
eventHandler.l.push(f)
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Removes an event listener.
|
|
44
|
+
*
|
|
45
|
+
* @template ARG0,ARG1
|
|
46
|
+
* @param {EventHandler<ARG0,ARG1>} eventHandler
|
|
47
|
+
* @param {function(ARG0,ARG1):void} f The event handler that was added with
|
|
48
|
+
* {@link EventHandler#addEventListener}
|
|
49
|
+
*
|
|
50
|
+
* @private
|
|
51
|
+
* @function
|
|
52
|
+
*/
|
|
53
|
+
export const removeEventHandlerListener = (eventHandler, f) => {
|
|
54
|
+
const l = eventHandler.l
|
|
55
|
+
const len = l.length
|
|
56
|
+
eventHandler.l = l.filter(g => f !== g)
|
|
57
|
+
if (len === eventHandler.l.length) {
|
|
58
|
+
console.error('[yjs] Tried to remove event handler that doesn\'t exist.')
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Removes all event listeners.
|
|
64
|
+
* @template ARG0,ARG1
|
|
65
|
+
* @param {EventHandler<ARG0,ARG1>} eventHandler
|
|
66
|
+
*
|
|
67
|
+
* @private
|
|
68
|
+
* @function
|
|
69
|
+
*/
|
|
70
|
+
export const removeAllEventHandlerListeners = eventHandler => {
|
|
71
|
+
eventHandler.l.length = 0
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Call all event listeners that were added via
|
|
76
|
+
* {@link EventHandler#addEventListener}.
|
|
77
|
+
*
|
|
78
|
+
* @template ARG0,ARG1
|
|
79
|
+
* @param {EventHandler<ARG0,ARG1>} eventHandler
|
|
80
|
+
* @param {ARG0} arg0
|
|
81
|
+
* @param {ARG1} arg1
|
|
82
|
+
*
|
|
83
|
+
* @private
|
|
84
|
+
* @function
|
|
85
|
+
*/
|
|
86
|
+
export const callEventHandlerListeners = (eventHandler, arg0, arg1) =>
|
|
87
|
+
f.callAll(eventHandler.l, [arg0, arg1])
|
package/src/utils/ID.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { YType } from '../internals.js' // eslint-disable-line
|
|
2
|
+
|
|
3
|
+
import * as decoding from 'lib0/decoding'
|
|
4
|
+
import * as encoding from 'lib0/encoding'
|
|
5
|
+
import * as error from 'lib0/error'
|
|
6
|
+
|
|
7
|
+
export class ID {
|
|
8
|
+
/**
|
|
9
|
+
* @param {number} client client id
|
|
10
|
+
* @param {number} clock unique per client id, continuous number
|
|
11
|
+
*/
|
|
12
|
+
constructor (client, clock) {
|
|
13
|
+
/**
|
|
14
|
+
* Client id
|
|
15
|
+
* @type {number}
|
|
16
|
+
*/
|
|
17
|
+
this.client = client
|
|
18
|
+
/**
|
|
19
|
+
* unique per client id, continuous number
|
|
20
|
+
* @type {number}
|
|
21
|
+
*/
|
|
22
|
+
this.clock = clock
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {ID | null} a
|
|
28
|
+
* @param {ID | null} b
|
|
29
|
+
* @return {boolean}
|
|
30
|
+
*
|
|
31
|
+
* @function
|
|
32
|
+
*/
|
|
33
|
+
export const compareIDs = (a, b) => a === b || (a !== null && b !== null && a.client === b.client && a.clock === b.clock)
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {number} client
|
|
37
|
+
* @param {number} clock
|
|
38
|
+
*
|
|
39
|
+
* @private
|
|
40
|
+
* @function
|
|
41
|
+
*/
|
|
42
|
+
export const createID = (client, clock) => new ID(client, clock)
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {encoding.Encoder} encoder
|
|
46
|
+
* @param {ID} id
|
|
47
|
+
*
|
|
48
|
+
* @private
|
|
49
|
+
* @function
|
|
50
|
+
*/
|
|
51
|
+
export const writeID = (encoder, id) => {
|
|
52
|
+
encoding.writeVarUint(encoder, id.client)
|
|
53
|
+
encoding.writeVarUint(encoder, id.clock)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Read ID.
|
|
58
|
+
* * If first varUint read is 0xFFFFFF a RootID is returned.
|
|
59
|
+
* * Otherwise an ID is returned
|
|
60
|
+
*
|
|
61
|
+
* @param {decoding.Decoder} decoder
|
|
62
|
+
* @return {ID}
|
|
63
|
+
*
|
|
64
|
+
* @private
|
|
65
|
+
* @function
|
|
66
|
+
*/
|
|
67
|
+
export const readID = decoder =>
|
|
68
|
+
createID(decoding.readVarUint(decoder), decoding.readVarUint(decoder))
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The top types are mapped from y.share.get(keyname) => type.
|
|
72
|
+
* `type` does not store any information about the `keyname`.
|
|
73
|
+
* This function finds the correct `keyname` for `type` and throws otherwise.
|
|
74
|
+
*
|
|
75
|
+
* @param {YType<any>} type
|
|
76
|
+
* @return {string}
|
|
77
|
+
*
|
|
78
|
+
* @private
|
|
79
|
+
* @function
|
|
80
|
+
*/
|
|
81
|
+
export const findRootTypeKey = type => {
|
|
82
|
+
// @ts-ignore _y must be defined, otherwise unexpected case
|
|
83
|
+
for (const [key, value] of type.doc.share.entries()) {
|
|
84
|
+
if (value === type) {
|
|
85
|
+
return key
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
throw error.unexpectedCase()
|
|
89
|
+
}
|