From 1d025ae73fe438055d63336f2d88cd6862d1bc94 Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Fri, 18 Apr 2025 20:26:05 +0200 Subject: [PATCH] rename AttributionManager=>IdMap The "AttributionManager" will be an abstract class that maps data (probably using IdMap(s)) --- src/index.js | 4 +- src/internals.js | 2 +- src/types/YText.js | 6 +- src/utils/{AttributionManager.js => IdMap.js} | 30 ++++----- src/utils/IdSet.js | 10 +-- ...ibutionManager.tests.js => IdMap.tests.js} | 66 +++++++++---------- tests/index.js | 4 +- tests/testHelper.js | 22 +++---- 8 files changed, 72 insertions(+), 72 deletions(-) rename src/utils/{AttributionManager.js => IdMap.js} (88%) rename tests/{AttributionManager.tests.js => IdMap.tests.js} (60%) diff --git a/src/index.js b/src/index.js index 5adfac56..5f9433c4 100644 --- a/src/index.js +++ b/src/index.js @@ -102,8 +102,8 @@ export { IdSet, equalIdSets, createDeleteSetFromStructStore, - AttributionManager, - createAttributionManager + IdMap, + createIdMap } from './internals.js' const glo = /** @type {any} */ (typeof globalThis !== 'undefined' diff --git a/src/internals.js b/src/internals.js index 6f9e5de2..f7005afd 100644 --- a/src/internals.js +++ b/src/internals.js @@ -40,4 +40,4 @@ export * from './structs/ContentString.js' export * from './structs/ContentType.js' export * from './structs/Item.js' export * from './structs/Skip.js' -export * from './utils/AttributionManager.js' +export * from './utils/IdMap.js' diff --git a/src/types/YText.js b/src/types/YText.js index 3e4b4986..0a70f371 100644 --- a/src/types/YText.js +++ b/src/types/YText.js @@ -26,7 +26,7 @@ import { updateMarkerChanges, ContentType, warnPrematureAccess, - ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction, AttributionManager, // eslint-disable-line + ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction, IdMap, // eslint-disable-line snapshot } from '../internals.js' @@ -999,13 +999,13 @@ export class YText extends AbstractType { * Note that deleted content that was not deleted in prevYdoc is rendered as an insertion with the * attribution `{ isDeleted: true, .. }`. * - * @param {AttributionManager} [attributionManager] + * @param {IdMap} [idMap] * @param {Doc} [prevYdoc] * @return {import('../utils/Delta.js').Delta} The Delta representation of this type. * * @public */ - getContent (attributionManager, prevYdoc) { + getContent (idMap, prevYdoc) { this.doc ?? warnPrematureAccess() const prevSnapshot = prevYdoc ? snapshot(prevYdoc) : null const d = delta.create() diff --git a/src/utils/AttributionManager.js b/src/utils/IdMap.js similarity index 88% rename from src/utils/AttributionManager.js rename to src/utils/IdMap.js index f8696407..03add22c 100644 --- a/src/utils/AttributionManager.js +++ b/src/utils/IdMap.js @@ -12,21 +12,21 @@ import * as array from 'lib0/array' * @param {T} attr * */ -const amAttrsHas = (attrs, attr) => attrs.find(a => a === attr) +const idmapAttrsHas = (attrs, attr) => attrs.find(a => a === attr) /** * @template T * @param {Array} a * @param {Array} b */ -export const amAttrsEqual = (a, b) => a.length === b.length && a.every(v => amAttrsHas(b, v)) +export const idmapAttrsEqual = (a, b) => a.length === b.length && a.every(v => idmapAttrsHas(b, v)) /** * @template T * @param {Array} a * @param {Array} b */ -const amAttrRangeJoin = (a, b) => a.concat(b.filter(attr => !amAttrsHas(a, attr))) +const idmapAttrRangeJoin = (a, b) => a.concat(b.filter(attr => !idmapAttrsHas(a, attr))) /** * @template Attrs @@ -132,7 +132,7 @@ export class AttrRanges { // merge range with nextRange const largerRange = range.len > nextRange.len ? range : nextRange const smallerLen = range.len < nextRange.len ? range.len : nextRange.len - ids[i] = new AttrRange(range.clock, smallerLen, amAttrRangeJoin(range.attrs, nextRange.attrs)) + ids[i] = new AttrRange(range.clock, smallerLen, idmapAttrRangeJoin(range.attrs, nextRange.attrs)) if (range.len === nextRange.len) { ids.splice(i + 1, 1) } else { @@ -152,7 +152,7 @@ export class AttrRanges { for (i = 1, j = 1; i < ids.length; i++) { const left = ids[j - 1] const right = ids[i] - if (left.clock + left.len === right.clock && amAttrsEqual(left.attrs, right.attrs)) { + if (left.clock + left.len === right.clock && idmapAttrsEqual(left.attrs, right.attrs)) { ids[j - 1] = new AttrRange(left.clock, left.len + right.len, left.attrs) } else if (right.len !== 0) { if (j < i) { @@ -169,11 +169,11 @@ export class AttrRanges { /** * @template T - * @param {Array>} ams - * @return {AttributionManager} A fresh IdSet + * @param {Array>} ams + * @return {IdMap} A fresh IdSet */ -export const mergeAttributionManagers = ams => { - const merged = createAttributionManager() +export const mergeIdMaps = ams => { + const merged = createIdMap() for (let amsI = 0; amsI < ams.length; amsI++) { ams[amsI].clients.forEach((rangesLeft, client) => { if (!merged.clients.has(client)) { @@ -196,7 +196,7 @@ export const mergeAttributionManagers = ams => { /** * @template Attrs */ -export class AttributionManager { +export class IdMap { constructor () { /** * @type {Map>} @@ -265,15 +265,15 @@ export class AttributionManager { } } -export const createAttributionManager = () => new AttributionManager() +export const createIdMap = () => new IdMap() /** - * Remove all ranges from `exclude` from `ds`. The result is a fresh AttributionManager containing all ranges from `idSet` that are not + * Remove all ranges from `exclude` from `ds`. The result is a fresh IdMap containing all ranges from `idSet` that are not * in `exclude`. * - * @template {AttributionManager} Set + * @template {IdMap} Set * @param {Set} set - * @param {IdSet | AttributionManager} exclude + * @param {IdSet | IdMap} exclude * @return {Set} */ -export const diffAttributionManager = _diffSet +export const diffIdMap = _diffSet diff --git a/src/utils/IdSet.js b/src/utils/IdSet.js index b3aa5df4..21efe141 100644 --- a/src/utils/IdSet.js +++ b/src/utils/IdSet.js @@ -4,7 +4,7 @@ import { splitItem, iterateStructs, UpdateEncoderV2, - AttributionManager, + IdMap, AttrRanges, AbstractStruct, DSDecoderV1, DSEncoderV1, DSDecoderV2, DSEncoderV2, Item, GC, StructStore, Transaction, ID // eslint-disable-line } from '../internals.js' @@ -217,16 +217,16 @@ export const insertIntoIdSet = (dest, src) => { * Remove all ranges from `exclude` from `ds`. The result is a fresh IdSet containing all ranges from `idSet` that are not * in `exclude`. * - * @template {IdSet | AttributionManager} Set + * @template {IdSet | IdMap} Set * @param {Set} set - * @param {IdSet | AttributionManager} exclude + * @param {IdSet | IdMap} exclude * @return {Set} */ export const _diffSet = (set, exclude) => { /** * @type {Set} */ - const res = /** @type {any } */ (set instanceof IdSet ? new IdSet() : new AttributionManager()) + const res = /** @type {any } */ (set instanceof IdSet ? new IdSet() : new IdMap()) const Ranges = set instanceof IdSet ? IdRanges : AttrRanges set.clients.forEach((_setRanges, client) => { /** @@ -288,7 +288,7 @@ export const _diffSet = (set, exclude) => { * * @template {IdSet} Set * @param {Set} set - * @param {IdSet | AttributionManager} exclude + * @param {IdSet | IdMap} exclude * @return {Set} */ export const diffIdSet = _diffSet diff --git a/tests/AttributionManager.tests.js b/tests/IdMap.tests.js similarity index 60% rename from tests/AttributionManager.tests.js rename to tests/IdMap.tests.js index 0ce8e835..a6692257 100644 --- a/tests/AttributionManager.tests.js +++ b/tests/IdMap.tests.js @@ -1,13 +1,13 @@ import * as t from 'lib0/testing' -import * as am from '../src/utils/AttributionManager.js' -import { compareAttributionManagers, createAttributionManager, ID, createRandomIdSet, createRandomAttributionManager } from './testHelper.js' +import * as am from '../src/utils/IdMap.js' +import { compareIdmaps, createIdMap, ID, createRandomIdSet, createRandomIdMap } from './testHelper.js' /** * @template T * @param {Array<[number, number, number, Array]>} ops */ const simpleConstructAttrs = ops => { - const attrs = createAttributionManager() + const attrs = createIdMap() ops.forEach(op => { attrs.add(op[0], op[1], op[2], op[3]) }) @@ -20,49 +20,49 @@ const simpleConstructAttrs = ops => { export const testAmMerge = _tc => { const attrs = [42] t.group('filter out empty items (1))', () => { - compareAttributionManagers( + compareIdmaps( simpleConstructAttrs([[0, 1, 0, attrs]]), simpleConstructAttrs([]) ) }) t.group('filter out empty items (2))', () => { - compareAttributionManagers( + compareIdmaps( simpleConstructAttrs([[0, 1, 0, attrs], [0, 2, 0, attrs]]), simpleConstructAttrs([]) ) }) t.group('filter out empty items (3 - end))', () => { - compareAttributionManagers( + compareIdmaps( simpleConstructAttrs([[0, 1, 1, attrs], [0, 2, 0, attrs]]), simpleConstructAttrs([[0, 1, 1, attrs]]) ) }) t.group('filter out empty items (4 - middle))', () => { - compareAttributionManagers( + compareIdmaps( simpleConstructAttrs([[0, 1, 1, attrs], [0, 2, 0, attrs], [0, 3, 1, attrs]]), simpleConstructAttrs([[0, 1, 1, attrs], [0, 3, 1, attrs]]) ) }) t.group('filter out empty items (5 - beginning))', () => { - compareAttributionManagers( + compareIdmaps( simpleConstructAttrs([[0, 1, 0, attrs], [0, 2, 1, attrs], [0, 3, 1, attrs]]), simpleConstructAttrs([[0, 2, 1, attrs], [0, 3, 1, attrs]]) ) }) t.group('merge of overlapping id ranges', () => { - compareAttributionManagers( + compareIdmaps( simpleConstructAttrs([[0, 1, 2, attrs], [0, 0, 2, attrs]]), simpleConstructAttrs([[0, 0, 3, attrs]]) ) }) t.group('construct without hole', () => { - compareAttributionManagers( + compareIdmaps( simpleConstructAttrs([[0, 1, 2, attrs], [0, 3, 1, attrs]]), simpleConstructAttrs([[0, 1, 3, attrs]]) ) }) t.group('no merge of overlapping id ranges with different attributes', () => { - compareAttributionManagers( + compareIdmaps( simpleConstructAttrs([[0, 1, 2, [1]], [0, 0, 2, [2]]]), simpleConstructAttrs([[0, 0, 1, [2]], [0, 1, 1, [1, 2]], [0, 2, 1, [1]]]) ) @@ -72,20 +72,20 @@ export const testAmMerge = _tc => { /** * @param {t.TestCase} tc */ -export const testRepeatMergingMultipleAttrManagers = tc => { +export const testRepeatMergingMultipleIdMaps = tc => { const clients = 4 const clockRange = 5 /** - * @type {Array>} + * @type {Array>} */ const sets = [] for (let i = 0; i < 3; i++) { - sets.push(createRandomAttributionManager(tc.prng, clients, clockRange, [1, 2, 3])) + sets.push(createRandomIdMap(tc.prng, clients, clockRange, [1, 2, 3])) } - const merged = am.mergeAttributionManagers(sets) - const mergedReverse = am.mergeAttributionManagers(sets.reverse()) - compareAttributionManagers(merged, mergedReverse) - const composed = am.createAttributionManager() + const merged = am.mergeIdMaps(sets) + const mergedReverse = am.mergeIdMaps(sets.reverse()) + compareIdmaps(merged, mergedReverse) + const composed = am.createIdMap() for (let iclient = 0; iclient < clients; iclient++) { for (let iclock = 0; iclock < clockRange + 42; iclock++) { const mergedHas = merged.has(new ID(iclient, iclock)) @@ -99,7 +99,7 @@ export const testRepeatMergingMultipleAttrManagers = tc => { } } } - compareAttributionManagers(merged, composed) + compareIdmaps(merged, composed) } /** @@ -109,12 +109,12 @@ export const testRepeatRandomDiffing = tc => { const clients = 4 const clockRange = 100 const attrs = [1, 2, 3] - const ds1 = createRandomAttributionManager(tc.prng, clients, clockRange, attrs) - const ds2 = createRandomAttributionManager(tc.prng, clients, clockRange, attrs) - const merged = am.mergeAttributionManagers([ds1, ds2]) - const e1 = am.diffAttributionManager(ds1, ds2) - const e2 = am.diffAttributionManager(merged, ds2) - compareAttributionManagers(e1, e2) + const ds1 = createRandomIdMap(tc.prng, clients, clockRange, attrs) + const ds2 = createRandomIdMap(tc.prng, clients, clockRange, attrs) + const merged = am.mergeIdMaps([ds1, ds2]) + const e1 = am.diffIdMap(ds1, ds2) + const e2 = am.diffIdMap(merged, ds2) + compareIdmaps(e1, e2) } /** @@ -124,13 +124,13 @@ export const testRepeatRandomDiffing2 = tc => { const clients = 4 const clockRange = 100 const attrs = [1, 2, 3] - const am1 = createRandomAttributionManager(tc.prng, clients, clockRange, attrs) - const am2 = createRandomAttributionManager(tc.prng, clients, clockRange, attrs) + const am1 = createRandomIdMap(tc.prng, clients, clockRange, attrs) + const am2 = createRandomIdMap(tc.prng, clients, clockRange, attrs) const idsExclude = createRandomIdSet(tc.prng, clients, clockRange) - const merged = am.mergeAttributionManagers([am1, am2]) - const mergedExcluded = am.diffAttributionManager(merged, idsExclude) - const e1 = am.diffAttributionManager(am1, idsExclude) - const e2 = am.diffAttributionManager(am2, idsExclude) - const excludedMerged = am.mergeAttributionManagers([e1, e2]) - compareAttributionManagers(mergedExcluded, excludedMerged) + const merged = am.mergeIdMaps([am1, am2]) + const mergedExcluded = am.diffIdMap(merged, idsExclude) + const e1 = am.diffIdMap(am1, idsExclude) + const e2 = am.diffIdMap(am2, idsExclude) + const excludedMerged = am.mergeIdMaps([e1, e2]) + compareIdmaps(mergedExcluded, excludedMerged) } diff --git a/tests/index.js b/tests/index.js index fd129a27..753174da 100644 --- a/tests/index.js +++ b/tests/index.js @@ -13,7 +13,7 @@ import * as updates from './updates.tests.js' import * as relativePositions from './relativePositions.tests.js' import * as delta from './delta.tests.js' import * as idset from './IdSet.tests.js' -import * as attributionManager from './AttributionManager.tests.js' +import * as idmap from './IdMap.tests.js' import { runTests } from 'lib0/testing' import { isBrowser, isNode } from 'lib0/environment' @@ -24,7 +24,7 @@ if (isBrowser) { } const tests = { - doc, map, array, text, xml, encoding, undoredo, compatibility, snapshot, updates, relativePositions, delta, idset, attributionManager + doc, map, array, text, xml, encoding, undoredo, compatibility, snapshot, updates, relativePositions, delta, idset, idmap } const run = async () => { diff --git a/tests/testHelper.js b/tests/testHelper.js index d7d89648..8b146797 100644 --- a/tests/testHelper.js +++ b/tests/testHelper.js @@ -8,7 +8,7 @@ import * as map from 'lib0/map' import * as Y from '../src/index.js' import * as math from 'lib0/math' import { - amAttrsEqual, createIdSet, createAttributionManager, addToIdSet + idmapAttrsEqual, createIdSet, createIdMap, addToIdSet } from '../src/internals.js' export * from '../src/index.js' @@ -329,10 +329,10 @@ export const compareIdSets = (idSet1, idSet2) => { /** * @template T - * @param {Y.AttributionManager} am1 - * @param {Y.AttributionManager} am2 + * @param {Y.IdMap} am1 + * @param {Y.IdMap} am2 */ -export const compareAttributionManagers = (am1, am2) => { +export const compareIdmaps = (am1, am2) => { if (am1.clients.size !== am2.clients.size) return false for (const [client, _items1] of am1.clients.entries()) { const items1 = _items1.getIds() @@ -340,8 +340,8 @@ export const compareAttributionManagers = (am1, am2) => { t.assert(items2 !== undefined && items1.length === items2.length) for (let i = 0; i < items1.length; i++) { const di1 = items1[i] - const di2 = /** @type {Array>} */ (items2)[i] - t.assert(di1.clock === di2.clock && di1.len === di2.len && amAttrsEqual(di1.attrs, di2.attrs)) + const di2 = /** @type {Array>} */ (items2)[i] + t.assert(di1.clock === di2.clock && di1.len === di2.len && idmapAttrsEqual(di1.attrs, di2.attrs)) } } return true @@ -374,12 +374,12 @@ export const createRandomIdSet = (gen, clients, clockRange) => { * @param {number} clients * @param {number} clockRange (max clock - exclusive - by each client) * @param {Array} attrChoices (max clock - exclusive - by each client) - * @return {Y.AttributionManager} + * @return {Y.IdMap} */ -export const createRandomAttributionManager = (gen, clients, clockRange, attrChoices) => { +export const createRandomIdMap = (gen, clients, clockRange, attrChoices) => { const maxOpLen = 5 const numOfOps = math.ceil((clients * clockRange) / maxOpLen) - const attrMngr = createAttributionManager() + const idMap = createIdMap() for (let i = 0; i < numOfOps; i++) { const client = prng.uint32(gen, 0, clients - 1) const clockStart = prng.uint32(gen, 0, clockRange) @@ -392,9 +392,9 @@ export const createRandomAttributionManager = (gen, clients, clockRange, attrCho attrs.push(a) } } - attrMngr.add(client, clockStart, len, attrs) + idMap.add(client, clockStart, len, attrs) } - return attrMngr + return idMap } /**