Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e2710ded9 | ||
|
|
227018f5c7 | ||
|
|
da8bacfc78 | ||
|
|
92bad63145 |
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "yjs",
|
||||
"version": "13.5.49",
|
||||
"version": "13.5.50",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "yjs",
|
||||
"version": "13.5.49",
|
||||
"version": "13.5.50",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lib0": "^0.2.49"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "yjs",
|
||||
"version": "13.5.49",
|
||||
"version": "13.5.50",
|
||||
"description": "Shared Editing Library",
|
||||
"main": "./dist/yjs.cjs",
|
||||
"module": "./dist/yjs.mjs",
|
||||
|
||||
@@ -1018,15 +1018,7 @@ export class YText extends AbstractType {
|
||||
str = ''
|
||||
}
|
||||
}
|
||||
// snapshots are merged again after the transaction, so we need to keep the
|
||||
// transalive until we are done
|
||||
transact(doc, transaction => {
|
||||
if (snapshot) {
|
||||
splitSnapshotAffectedStructs(transaction, snapshot)
|
||||
}
|
||||
if (prevSnapshot) {
|
||||
splitSnapshotAffectedStructs(transaction, prevSnapshot)
|
||||
}
|
||||
const computeDelta = () => {
|
||||
while (n !== null) {
|
||||
if (isVisible(n, snapshot) || (prevSnapshot !== undefined && isVisible(n, prevSnapshot))) {
|
||||
switch (n.content.constructor) {
|
||||
@@ -1079,7 +1071,22 @@ export class YText extends AbstractType {
|
||||
n = n.right
|
||||
}
|
||||
packStr()
|
||||
}, 'cleanup')
|
||||
}
|
||||
if (snapshot || prevSnapshot) {
|
||||
// snapshots are merged again after the transaction, so we need to keep the
|
||||
// transaction alive until we are done
|
||||
transact(doc, transaction => {
|
||||
if (snapshot) {
|
||||
splitSnapshotAffectedStructs(transaction, snapshot)
|
||||
}
|
||||
if (prevSnapshot) {
|
||||
splitSnapshotAffectedStructs(transaction, prevSnapshot)
|
||||
}
|
||||
computeDelta()
|
||||
}, 'cleanup')
|
||||
} else {
|
||||
computeDelta()
|
||||
}
|
||||
return ops
|
||||
}
|
||||
|
||||
|
||||
@@ -257,8 +257,7 @@ export class YXmlFragment extends AbstractType {
|
||||
* @return {string} The string representation of all children.
|
||||
*/
|
||||
toString () {
|
||||
// toString can result in many cleanup transactions. We wrap all cleanup transactions here to reduce the work
|
||||
return transact(/** @type {Doc} */ (this.doc), () => typeListMap(this, xml => xml.toString()).join(''))
|
||||
return typeListMap(this, xml => xml.toString()).join('')
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -156,13 +156,15 @@ export class Doc extends Observable {
|
||||
* that happened inside of the transaction are sent as one message to the
|
||||
* other peers.
|
||||
*
|
||||
* @param {function(Transaction):void} f The function that should be executed as a transaction
|
||||
* @template T
|
||||
* @param {function(Transaction):T} f The function that should be executed as a transaction
|
||||
* @param {any} [origin] Origin of who started the transaction. Will be stored on transaction.origin
|
||||
* @return T
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
transact (f, origin = null) {
|
||||
transact(this, f, origin)
|
||||
return transact(this, f, origin)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -130,6 +130,11 @@ export class YEvent {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a computed property. Note that this can only be safely computed during the
|
||||
* event call. Computing this property after other changes happened might result in
|
||||
* unexpected behavior (incorrect computation of deltas). A safe way to collect changes
|
||||
* is to store the `changes` or the `delta` object. Avoid storing the `transaction` object.
|
||||
*
|
||||
* @type {Array<{insert?: string | Array<any> | object | AbstractType<any>, retain?: number, delete?: number, attributes?: Object<string, any>}>}
|
||||
*/
|
||||
get delta () {
|
||||
@@ -149,6 +154,11 @@ export class YEvent {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a computed property. Note that this can only be safely computed during the
|
||||
* event call. Computing this property after other changes happened might result in
|
||||
* unexpected behavior (incorrect computation of deltas). A safe way to collect changes
|
||||
* is to store the `changes` or the `delta` object. Avoid storing the `transaction` object.
|
||||
*
|
||||
* @type {{added:Set<Item>,deleted:Set<Item>,keys:Map<string,{action:'add'|'update'|'delete',oldValue:any}>,delta:Array<{insert?:Array<any>|string, delete?:number, retain?:number}>}}
|
||||
*/
|
||||
get changes () {
|
||||
|
||||
@@ -33,7 +33,7 @@ export const testOriginInTransaction = _tc => {
|
||||
doc.on('afterTransaction', (tr) => {
|
||||
origins.push(tr.origin)
|
||||
if (origins.length <= 1) {
|
||||
ytext.toDelta()
|
||||
ytext.toDelta(Y.snapshot(doc)) // adding a snapshot forces toDelta to create a cleanup transaction
|
||||
doc.transact(() => {
|
||||
ytext.insert(0, 'a')
|
||||
}, 'nested')
|
||||
|
||||
@@ -1747,9 +1747,9 @@ export const testBasicFormat = tc => {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} tc
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
export const testMultilineFormat = tc => {
|
||||
export const testMultilineFormat = _tc => {
|
||||
const ydoc = new Y.Doc()
|
||||
const testText = ydoc.getText('test')
|
||||
testText.insert(0, 'Test\nMulti-line\nFormatting')
|
||||
@@ -1770,9 +1770,9 @@ export const testMultilineFormat = tc => {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} tc
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
export const testNotMergeEmptyLinesFormat = tc => {
|
||||
export const testNotMergeEmptyLinesFormat = _tc => {
|
||||
const ydoc = new Y.Doc()
|
||||
const testText = ydoc.getText('test')
|
||||
testText.applyDelta([
|
||||
@@ -1790,9 +1790,9 @@ export const testNotMergeEmptyLinesFormat = tc => {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} tc
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
export const testPreserveAttributesThroughDelete = tc => {
|
||||
export const testPreserveAttributesThroughDelete = _tc => {
|
||||
const ydoc = new Y.Doc()
|
||||
const testText = ydoc.getText('test')
|
||||
testText.applyDelta([
|
||||
@@ -2046,9 +2046,9 @@ const id = Y.createID(0, 0)
|
||||
const c = new Y.ContentString('a')
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} tc
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
export const testBestCase = tc => {
|
||||
export const testBestCase = _tc => {
|
||||
const N = largeDocumentSize
|
||||
const items = new Array(N)
|
||||
t.measureTime('time to create two million items in the best case', () => {
|
||||
@@ -2085,9 +2085,9 @@ const tryGc = () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} tc
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
export const testLargeFragmentedDocument = tc => {
|
||||
export const testLargeFragmentedDocument = _tc => {
|
||||
const itemsToInsert = largeDocumentSize
|
||||
let update = /** @type {any} */ (null)
|
||||
;(() => {
|
||||
@@ -2117,9 +2117,9 @@ export const testLargeFragmentedDocument = tc => {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} tc
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
export const testIncrementalUpdatesPerformanceOnLargeFragmentedDocument = tc => {
|
||||
export const testIncrementalUpdatesPerformanceOnLargeFragmentedDocument = _tc => {
|
||||
const itemsToInsert = largeDocumentSize
|
||||
const updates = /** @type {Array<Uint8Array>} */ ([])
|
||||
;(() => {
|
||||
@@ -2227,9 +2227,9 @@ export const testSearchMarkerBug1 = tc => {
|
||||
/**
|
||||
* Reported in https://github.com/yjs/yjs/pull/32
|
||||
*
|
||||
* @param {t.TestCase} tc
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
export const testFormattingBug = async tc => {
|
||||
export const testFormattingBug = async _tc => {
|
||||
const ydoc1 = new Y.Doc()
|
||||
const ydoc2 = new Y.Doc()
|
||||
const text1 = ydoc1.getText()
|
||||
@@ -2252,9 +2252,9 @@ export const testFormattingBug = async tc => {
|
||||
/**
|
||||
* Delete formatting should not leave redundant formatting items.
|
||||
*
|
||||
* @param {t.TestCase} tc
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
export const testDeleteFormatting = tc => {
|
||||
export const testDeleteFormatting = _tc => {
|
||||
const doc = new Y.Doc()
|
||||
const text = doc.getText()
|
||||
text.insert(0, 'Attack ships on fire off the shoulder of Orion.')
|
||||
@@ -2456,6 +2456,41 @@ const qChanges = [
|
||||
}
|
||||
ops.push({ insert: text }, { insert: '\n', format: { 'code-block': true } })
|
||||
ytext.applyDelta(ops)
|
||||
},
|
||||
/**
|
||||
* @param {Y.Doc} y
|
||||
* @param {prng.PRNG} gen
|
||||
*/
|
||||
(y, gen) => { // complex delta op
|
||||
const ytext = y.getText('text')
|
||||
const contentLen = ytext.toString().length
|
||||
let currentPos = math.max(0, prng.int32(gen, 0, contentLen - 1))
|
||||
/**
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
const ops = currentPos > 0 ? [{ retain: currentPos }] : []
|
||||
// create max 3 ops
|
||||
for (let i = 0; i < 7 && currentPos < contentLen; i++) {
|
||||
prng.oneOf(gen, [
|
||||
() => { // format
|
||||
const retain = math.min(prng.int32(gen, 0, contentLen - currentPos), 5)
|
||||
const format = prng.oneOf(gen, marks)
|
||||
ops.push({ retain, attributes: format })
|
||||
currentPos += retain
|
||||
},
|
||||
() => { // insert
|
||||
const attrs = prng.oneOf(gen, marksChoices)
|
||||
const text = prng.word(gen, 1, 3)
|
||||
ops.push({ insert: text, attributes: attrs })
|
||||
},
|
||||
() => { // delete
|
||||
const delLen = math.min(prng.int32(gen, 0, contentLen - currentPos), 10)
|
||||
ops.push({ delete: delLen })
|
||||
currentPos += delLen
|
||||
}
|
||||
])()
|
||||
}
|
||||
ytext.applyDelta(ops)
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user