started refactor expose a single Yjs type only using lib0@v1 delta

This commit is contained in:
Kevin Jahns
2025-12-28 14:52:57 +01:00
parent 301d3836ab
commit 69131b76c8
16 changed files with 2319 additions and 220 deletions

View File

@@ -24,7 +24,7 @@ export {
ContentAny,
ContentString,
ContentType,
AbstractType,
YType as AbstractType,
getTypeChildren,
createRelativePositionFromTypeIndex,
createRelativePositionFromJSON,

View File

@@ -19,16 +19,7 @@ export * from './utils/StructSet.js'
export * from './utils/IdMap.js'
export * from './utils/AttributionManager.js'
export * from './utils/delta-helpers.js'
export * from './types/AbstractType.js'
export * from './types/YArray.js'
export * from './types/YMap.js'
export * from './types/YText.js'
export * from './types/YXmlFragment.js'
export * from './types/YXmlElement.js'
export * from './types/YXmlHook.js'
export * from './types/YXmlText.js'
export * from './ytype.js'
export * from './structs/AbstractStruct.js'
export * from './structs/GC.js'
export * from './structs/ContentBinary.js'

View File

@@ -22,7 +22,7 @@ import {
readContentType,
addChangedTypeToTransaction,
addStructToIdSet,
IdSet, StackItem, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ContentType, ContentDeleted, StructStore, ID, AbstractType, Transaction, // eslint-disable-line
IdSet, StackItem, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ContentType, ContentDeleted, StructStore, ID, YType, Transaction, // eslint-disable-line
} from '../internals.js'
import * as error from 'lib0/error'
@@ -282,7 +282,7 @@ export class Item extends AbstractStruct {
* @param {ID | null} origin
* @param {Item | null} right
* @param {ID | null} rightOrigin
* @param {AbstractType<any,any>|ID|null} parent Is a type if integrated, is null if it is possible to copy parent from left or right, is ID before integration to search for it.
* @param {YType<any,any>|ID|null} parent Is a type if integrated, is null if it is possible to copy parent from left or right, is ID before integration to search for it.
* @param {string | null} parentSub
* @param {AbstractContent} content
*/
@@ -309,7 +309,7 @@ export class Item extends AbstractStruct {
*/
this.rightOrigin = rightOrigin
/**
* @type {AbstractType<any,any>|ID|null}
* @type {YType<any,any>|ID|null}
*/
this.parent = parent
/**
@@ -696,7 +696,7 @@ export class Item extends AbstractStruct {
encoder.writeRightID(rightOrigin)
}
if (origin === null && rightOrigin === null) {
const parent = /** @type {AbstractType<any>} */ (this.parent)
const parent = /** @type {YType<any>} */ (this.parent)
if (parent._item !== undefined) {
const parentItem = parent._item
if (parentItem === null) {

View File

@@ -1,25 +0,0 @@
import { ObservableV2 } from 'lib0/observable'
import {
Doc // eslint-disable-line
} from '../internals.js'
/**
* This is an abstract interface that all Connectors should implement to keep them interchangeable.
*
* @note This interface is experimental and it is not advised to actually inherit this class.
* It just serves as typing information.
*
* @extends {ObservableV2<any>}
*/
export class AbstractConnector extends ObservableV2 {
/**
* @param {Doc} ydoc
* @param {any} awareness
*/
constructor (ydoc, awareness) {
super()
this.doc = ydoc
this.awareness = awareness
}
}

View File

@@ -4,12 +4,7 @@
import {
StructStore,
AbstractType,
YArray,
YText,
YMap,
YXmlElement,
YXmlFragment,
YType,
transact,
applyUpdate,
ContentDoc, Item, Transaction, // eslint-disable-line
@@ -24,13 +19,6 @@ import * as promise from 'lib0/promise'
export const generateNewClientId = random.uint32
/**
* @typedef {import('../utils/types.js').YTypeConstructors} YTypeConstructors
*/
/**
* @typedef {import('../utils/types.js').YType} YType
*/
/**
* @typedef {Object} DocOpts
* @property {boolean} [DocOpts.gc=true] Disable garbage collection (default: gc=true)
@@ -212,105 +200,17 @@ export class Doc extends ObservableV2 {
* Define all types right after the Y.Doc instance is created and store them in a separate object.
* Also use the typed methods `getText(name)`, `getArray(name)`, ..
*
* @template {YTypeConstructors} [TypeC=typeof AbstractType]
* @example
* const ydoc = new Y.Doc(..)
* const appState = {
* document: ydoc.getText('document')
* comments: ydoc.getArray('comments')
* }
* @param {string} key
* @param {string?} name Type-name
*
* @param {string} name
* @param {TypeC} TypeConstructor The constructor of the type definition. E.g. Y.Text, Y.Array, Y.Map, ...
* @return {AbstractType} The created type. Constructed with TypeConstructor
*
* @public
* @return {YType}
*/
get (name, TypeConstructor = /** @type {any} */ (AbstractType)) {
const type = map.setIfUndefined(this.share, name, () => {
// @ts-ignore
const t = new TypeConstructor()
get (key, name = null) {
return map.setIfUndefined(this.share, key, () => {
const t = new YType(name)
t._integrate(this, null)
return t
})
const Constr = type.constructor
// @ts-ignore
if (TypeConstructor !== AbstractType && Constr !== TypeConstructor) {
if (Constr === AbstractType) {
// @ts-ignore
const t = new TypeConstructor()
t._map = type._map
type._map.forEach(/** @param {Item?} n */ n => {
for (; n !== null; n = n.left) {
// @ts-ignore
n.parent = t
}
})
t._start = type._start
for (let n = t._start; n !== null; n = n.right) {
n.parent = t
}
t._length = type._length
this.share.set(name, t)
t._integrate(this, null)
return /** @type {InstanceType<TypeC>} */ (t)
} else {
throw new Error(`Type with the name ${name} has already been defined with a different constructor`)
}
}
return /** @type {InstanceType<TypeC>} */ (type)
}
/**
* @template T
* @param {string} [name]
* @return {YArray<T>}
*
* @public
*/
getArray (name = '') {
return /** @type {YArray<any>} */ (this.get(name, YArray))
}
/**
* @param {string} [name]
* @return {YText}
*
* @public
*/
getText (name = '') {
return /** @type {YText} */ (this.get(name, YText))
}
/**
* @template T
* @param {string} [name]
* @return {YMap<T>}
*
* @public
*/
getMap (name = '') {
return /** @type {YMap<T>} */ (this.get(name, YMap))
}
/**
* @param {string} [name]
* @return {YXmlElement}
*
* @public
*/
getXmlElement (name = '') {
return /** @type {YXmlElement<{[key:string]:string}>} */ (this.get(name, YXmlElement))
}
/**
* @param {string} [name]
* @return {YXmlFragment}
*
* @public
*/
getXmlFragment (name = '') {
return /** @type {YXmlFragment} */ (this.get(name, YXmlFragment))
}
/**
@@ -326,11 +226,9 @@ export class Doc extends ObservableV2 {
* @type {Object<string, any>}
*/
const doc = {}
this.share.forEach((value, key) => {
doc[key] = value.toJSON()
})
return doc
}

View File

@@ -1,4 +1,4 @@
import { AbstractType } from '../internals.js' // eslint-disable-line
import { YType } from '../internals.js' // eslint-disable-line
import * as decoding from 'lib0/decoding'
import * as encoding from 'lib0/encoding'
@@ -72,7 +72,7 @@ export const readID = decoder =>
* `type` does not store any information about the `keyname`.
* This function finds the correct `keyname` for `type` and throws otherwise.
*
* @param {AbstractType<any>} type
* @param {YType<any>} type
* @return {string}
*
* @private

View File

@@ -9,7 +9,7 @@ import {
ContentType,
followRedone,
getItem,
StructStore, ID, Doc, AbstractType, noAttributionsManager, // eslint-disable-line
StructStore, ID, Doc, YType, noAttributionsManager, // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding'
@@ -106,13 +106,13 @@ export const createRelativePositionFromJSON = json => new RelativePosition(json.
export class AbsolutePosition {
/**
* @param {AbstractType<any>} type
* @param {YType<any>} type
* @param {number} index
* @param {number} [assoc]
*/
constructor (type, index, assoc = 0) {
/**
* @type {AbstractType<any>}
* @type {YType<any>}
*/
this.type = type
/**
@@ -124,7 +124,7 @@ export class AbsolutePosition {
}
/**
* @param {AbstractType<any>} type
* @param {YType<any>} type
* @param {number} index
* @param {number} [assoc]
*
@@ -133,7 +133,7 @@ export class AbsolutePosition {
export const createAbsolutePosition = (type, index, assoc = 0) => new AbsolutePosition(type, index, assoc)
/**
* @param {AbstractType<any>} type
* @param {YType<any>} type
* @param {ID|null} item
* @param {number} [assoc]
*
@@ -153,7 +153,7 @@ export const createRelativePosition = (type, item, assoc) => {
/**
* Create a relativePosition based on a absolute position.
*
* @param {AbstractType} type The base type (e.g. YText or YArray).
* @param {YType} type The base type (e.g. YText or YArray).
* @param {number} index The absolute position.
* @param {number} [assoc]
* @param {import('../utils/AttributionManager.js').AbstractAttributionManager} attributionManager
@@ -304,7 +304,7 @@ export const createAbsolutePositionFromRelativePosition = (rpos, doc, followUndo
if (!(right instanceof Item)) {
return null
}
type = /** @type {AbstractType<any>} */ (right.parent)
type = /** @type {YType<any>} */ (right.parent)
if (type._item === null || !type._item.deleted) {
index = attributionManager.contentLength(right) === 0 ? 0 : (res.diff + (assoc >= 0 ? 0 : 1)) // adjust position based on left association if necessary
let n = right.left

View File

@@ -9,10 +9,12 @@ import {
Item,
generateNewClientId,
createID,
cleanupYTextAfterTransaction,
IdSet, UpdateEncoderV1, UpdateEncoderV2, GC, StructStore, AbstractType, AbstractStruct, YEvent, Doc // eslint-disable-line
iterateStructsByIdSet,
ContentFormat,
IdSet, UpdateEncoderV1, UpdateEncoderV2, GC, StructStore, AbstractStruct, YEvent, Doc // eslint-disable-line
} from '../internals.js'
import {YType} from '../ytype.js'
import * as error from 'lib0/error'
import * as map from 'lib0/map'
import * as math from 'lib0/math'
@@ -84,13 +86,13 @@ export class Transaction {
* All types that were directly modified (property added or child
* inserted/deleted). New types are not included in this Set.
* Maps from type to parentSubs (`item.parentSub = null` for YArray)
* @type {Map<import('../utils/types.js').YType,Set<String|null>>}
* @type {Map<YType,Set<String|null>>}
*/
this.changed = new Map()
/**
* Stores the events for the types that observe also child elements.
* It is mainly used by `observeDeep`.
* @type {Map<import('../utils/types.js').YType,Array<YEvent<any>>>}
* @type {Map<YType,Array<YEvent<any>>>}
*/
this.changedParentTypes = new Map()
/**
@@ -198,7 +200,7 @@ export const nextID = transaction => {
* did not change, it was just added and we should not fire events for `type`.
*
* @param {Transaction} transaction
* @param {import('../utils/types.js').YType} type
* @param {YType} type
* @param {string|null} parentSub
*/
export const addChangedTypeToTransaction = (transaction, type, parentSub) => {
@@ -220,8 +222,8 @@ const tryToMergeWithLefts = (structs, pos) => {
for (; i > 0; right = left, left = structs[--i - 1]) {
if (left.deleted === right.deleted && left.constructor === right.constructor) {
if (left.mergeWith(right)) {
if (right instanceof Item && right.parentSub !== null && /** @type {AbstractType<any>} */ (right.parent)._map.get(right.parentSub) === right) {
/** @type {AbstractType<any>} */ (right.parent)._map.set(right.parentSub, /** @type {Item} */ (left))
if (right instanceof Item && right.parentSub !== null && /** @type {YType} */ (right.parent)._map.get(right.parentSub) === right) {
/** @type {YType} */ (right.parent)._map.set(right.parentSub, /** @type {Item} */ (left))
}
continue
}
@@ -300,6 +302,200 @@ export const tryGc = (tr, idset, gcFilter) => {
tryMerge(idset, tr.doc.store)
}
/**
* @param {Transaction} transaction
* @param {Item | null} item
*/
const cleanupContextlessFormattingGap = (transaction, item) => {
if (!transaction.doc.cleanupFormatting) return 0
// iterate until item.right is null or content
while (item && item.right && (item.right.deleted || !item.right.countable)) {
item = item.right
}
const attrs = new Set()
// iterate back until a content item is found
while (item && (item.deleted || !item.countable)) {
if (!item.deleted && item.content.constructor === ContentFormat) {
const key = /** @type {ContentFormat} */ (item.content).key
if (attrs.has(key)) {
item.delete(transaction)
transaction.cleanUps.add(item.id.client, item.id.clock, item.length)
} else {
attrs.add(key)
}
}
item = item.left
}
}
/**
* @param {Map<string,any>} currentAttributes
* @param {ContentFormat} format
*
* @private
* @function
*/
const updateCurrentAttributes = (currentAttributes, { key, value }) => {
if (value === null) {
currentAttributes.delete(key)
} else {
currentAttributes.set(key, value)
}
}
/**
* Call this function after string content has been deleted in order to
* clean up formatting Items.
*
* @param {Transaction} transaction
* @param {Item} start
* @param {Item|null} curr exclusive end, automatically iterates to the next Content Item
* @param {Map<string,any>} startAttributes
* @param {Map<string,any>} currAttributes
* @return {number} The amount of formatting Items deleted.
*
* @function
*/
export const cleanupFormattingGap = (transaction, start, curr, startAttributes, currAttributes) => {
if (!transaction.doc.cleanupFormatting) return 0
/**
* @type {Item|null}
*/
let end = start
/**
* @type {Map<string,ContentFormat>}
*/
const endFormats = map.create()
while (end && (!end.countable || end.deleted)) {
if (!end.deleted && end.content.constructor === ContentFormat) {
const cf = /** @type {ContentFormat} */ (end.content)
endFormats.set(cf.key, cf)
}
end = end.right
}
let cleanups = 0
let reachedCurr = false
while (start !== end) {
if (curr === start) {
reachedCurr = true
}
if (!start.deleted) {
const content = start.content
switch (content.constructor) {
case ContentFormat: {
const { key, value } = /** @type {ContentFormat} */ (content)
const startAttrValue = startAttributes.get(key) ?? null
if (endFormats.get(key) !== content || startAttrValue === value) {
// Either this format is overwritten or it is not necessary because the attribute already existed.
start.delete(transaction)
transaction.cleanUps.add(start.id.client, start.id.clock, start.length)
cleanups++
if (!reachedCurr && (currAttributes.get(key) ?? null) === value && startAttrValue !== value) {
if (startAttrValue === null) {
currAttributes.delete(key)
} else {
currAttributes.set(key, startAttrValue)
}
}
}
if (!reachedCurr && !start.deleted) {
updateCurrentAttributes(currAttributes, /** @type {ContentFormat} */ (content))
}
break
}
}
}
start = /** @type {Item} */ (start.right)
}
return cleanups
}
/**
* This function is experimental and subject to change / be removed.
*
* Ideally, we don't need this function at all. Formatting attributes should be cleaned up
* automatically after each change. This function iterates twice over the complete YText type
* and removes unnecessary formatting attributes. This is also helpful for testing.
*
* This function won't be exported anymore as soon as there is confidence that the YText type works as intended.
*
* @param {YType} type
* @return {number} How many formatting attributes have been cleaned up.
*/
export const cleanupYTextFormatting = type => {
if (!type.doc?.cleanupFormatting) return 0
let res = 0
transact(/** @type {Doc} */ (type.doc), transaction => {
let start = /** @type {Item} */ (type._start)
let end = type._start
let startAttributes = map.create()
const currentAttributes = map.copy(startAttributes)
while (end) {
if (end.deleted === false) {
switch (end.content.constructor) {
case ContentFormat:
updateCurrentAttributes(currentAttributes, /** @type {ContentFormat} */ (end.content))
break
default:
res += cleanupFormattingGap(transaction, start, end, startAttributes, currentAttributes)
startAttributes = map.copy(currentAttributes)
start = end
break
}
}
end = end.right
}
})
return res
}
/**
* This will be called by the transaction once the event handlers are called to potentially cleanup
* formatting attributes.
*
* @param {Transaction} transaction
*/
export const cleanupYTextAfterTransaction = transaction => {
/**
* @type {Set<YType>}
*/
const needFullCleanup = new Set()
// check if another formatting item was inserted
const doc = transaction.doc
iterateStructsByIdSet(transaction, transaction.insertSet, (item) => {
if (
!item.deleted && /** @type {Item} */ (item).content.constructor === ContentFormat && item.constructor !== GC
) {
needFullCleanup.add(/** @type {any} */ (item).parent)
}
})
// cleanup in a new transaction
transact(doc, (t) => {
iterateStructsByIdSet(transaction, transaction.deleteSet, item => {
if (item instanceof GC || !(/** @type {YType} */ (item.parent)._hasFormatting) || needFullCleanup.has(/** @type {YType} */ (item.parent))) {
return
}
const parent = /** @type {YType} */ (item.parent)
if (item.content.constructor === ContentFormat) {
needFullCleanup.add(parent)
} else {
// If no formatting attribute was inserted or deleted, we can make due with contextless
// formatting cleanups.
// Contextless: it is not necessary to compute currentAttributes for the affected position.
cleanupContextlessFormattingGap(t, item)
}
})
// If a formatting item was inserted, we simply clean the whole type.
// We need to compute currentAttributes for the current position anyway.
for (const yText of needFullCleanup) {
cleanupYTextFormatting(yText)
}
})
}
/**
* @param {Array<Transaction>} transactionCleanups
* @param {number} i
@@ -352,7 +548,12 @@ const cleanupTransactions = (transactionCleanups, i) => {
.sort((event1, event2) => event1.path.length - event2.path.length)
// We don't need to check for events.length
// because we know it has at least one element
callEventHandlerListeners(type._dEH, events, transaction)
/**
* @type {YEvent<any>}
*/
const deepEventHandler = events.find(event => event.target === type) || new YEvent(type, transaction, new Set(null))
callEventHandlerListeners(type._dEH, deepEventHandler, transaction)
}
})
})

View File

@@ -8,7 +8,7 @@ import {
isParentOf,
followRedone,
getItemCleanStart,
YEvent, Transaction, Doc, Item, GC, IdSet, AbstractType // eslint-disable-line
YEvent, Transaction, Doc, Item, GC, IdSet, YType // eslint-disable-line
} from '../internals.js'
import * as time from 'lib0/time'
@@ -273,7 +273,7 @@ export class UndoManager extends ObservableV2 {
ytypes.forEach(ytype => {
if (!tmpSet.has(ytype)) {
tmpSet.add(ytype)
if (ytype instanceof AbstractType ? ytype.doc !== this.doc : ytype !== this.doc) logging.warn('[yjs#509] Not same Y.Doc') // use MultiDocUndoManager instead. also see https://github.com/yjs/yjs/issues/509
if (ytype instanceof YType ? ytype.doc !== this.doc : ytype !== this.doc) logging.warn('[yjs#509] Not same Y.Doc') // use MultiDocUndoManager instead. also see https://github.com/yjs/yjs/issues/509
this.scope.push(ytype)
}
})

View File

@@ -2,7 +2,7 @@ import {
diffIdSet,
mergeIdSets,
noAttributionsManager,
Doc, AbstractAttributionManager, Item, AbstractType, Transaction, AbstractStruct, // eslint-disable-line
YType, Doc, AbstractAttributionManager, Item, Transaction, AbstractStruct, // eslint-disable-line
createAbsolutePositionFromRelativePosition,
createRelativePosition,
AbsolutePosition
@@ -18,19 +18,19 @@ import * as set from 'lib0/set'
*/
export class YEvent {
/**
* @param {AbstractType<DConf>} target The changed type.
* @param {YType<DConf>} target The changed type.
* @param {Transaction} transaction
* @param {Set<any>?} subs The keys that changed
*/
constructor (target, transaction, subs) {
/**
* The type on which this event was created on.
* @type {AbstractType<DConf>}
* @type {YType<DConf>}
*/
this.target = target
/**
* The current target on which the observe callback is called.
* @type {AbstractType<any>}
* @type {YType<any>}
*/
this.currentTarget = target
/**
@@ -39,11 +39,11 @@ export class YEvent {
*/
this.transaction = transaction
/**
* @type {delta.Delta<DConf>|null}
* @type {import('../ytype.js').DeltaConfTypesToDelta<DConf>|null}
*/
this._delta = null
/**
* @type {import('../types/AbstractType.js').DeltaConfTypesToDeltaDelta<DConf>|null}
* @type {delta.Delta<DConf>|null}
*/
this._deltaDeep = null
/**
@@ -125,7 +125,7 @@ export class YEvent {
/**
* @todo this should be done only one in the transaction step
*
* @type {Map<import('./types.js').YType,Set<string|null>>|null}
* @type {Map<YType,Set<string|null>>|null}
*/
let modified = this.transaction.changed
if (deep) {
@@ -184,8 +184,8 @@ export class YEvent {
* console.log(path) // might look like => [2, 'key1']
* child === type.get(path[0]).get(path[1])
*
* @param {AbstractType} parent
* @param {AbstractType} child target
* @param {YType} parent
* @param {YType} child target
* @param {AbstractAttributionManager} am
* @return {Array<string|number>} Path to the target
*
@@ -205,7 +205,7 @@ export const getPathTo = (parent, child, am = noAttributionsManager) => {
const apos = /** @type {AbsolutePosition} */ (createAbsolutePositionFromRelativePosition(createRelativePosition(parent, child._item.id), doc, false, am))
path.unshift(apos.index)
}
child = /** @type {AbstractType} */ (child._item.parent)
child = /** @type {YType} */ (child._item.parent)
}
return path
}

View File

@@ -5,7 +5,7 @@ import {
diffIdSet,
mergeIdSets,
Item,
AbstractType, Doc, // eslint-disable-line
YType, Doc, // eslint-disable-line
iterateStructsByIdSet
} from '../internals.js'
import * as delta from 'lib0/delta'
@@ -28,12 +28,12 @@ export const diffDocsToDelta = (v1, v2, { am = createAttributionManagerFromDiff(
const deletesOnly = diffIdSet(deleteDiff, insertDiff)
const itemsToRender = mergeIdSets([insertsOnly, deleteDiff])
/**
* @type {Map<AbstractType, Set<string|null>>}
* @type {Map<YType, Set<string|null>>}
*/
const changedTypes = new Map()
iterateStructsByIdSet(tr, itemsToRender, /** @param {any} item */ item => {
while (item instanceof Item) {
const parent = /** @type {AbstractType} */ (item.parent)
const parent = /** @type {YType} */ (item.parent)
const conf = map.setIfUndefined(changedTypes, parent, set.create)
if (conf.has(item.parentSub)) break // has already been marked as modified
conf.add(item.parentSub)

View File

@@ -1,9 +1,9 @@
import { AbstractType, Item } from '../internals.js' // eslint-disable-line
import { Item } from '../internals.js' // eslint-disable-line
/**
* Check if `parent` is a parent of `child`.
*
* @param {import('../utils/types.js').YType} parent
* @param {import('../ytype.js').YType} parent
* @param {Item|null} child
* @return {Boolean} Whether `parent` is a parent of `child`.
*
@@ -15,7 +15,7 @@ export const isParentOf = (parent, child) => {
if (child.parent === parent) {
return true
}
child = /** @type {AbstractType<any>} */ (child.parent)._item
child = /** @type {import('../ytype.js').YType} */ (child.parent)._item
}
return false
}

View File

@@ -1,5 +1,5 @@
import {
AbstractType // eslint-disable-line
YType // eslint-disable-line
} from '../internals.js'
/**
@@ -7,7 +7,7 @@ import {
*
* Do not use in productive systems as the output can be immense!
*
* @param {AbstractType<any>} type
* @param {YType<any>} type
*/
export const logType = type => {
const res = []

View File

@@ -1,28 +1,3 @@
/**
* @typedef {import('../types/YArray.js').YArray<any>
* | import('../types/YMap.js').YMap<any>
* | import('../types/YText.js').YText<any>
* | import('../types/YXmlFragment.js').YXmlFragment<any,any>
* | import('../types/YXmlElement.js').YXmlElement<any,any>
* | import('../types/YXmlHook.js').YXmlHook
* | import('../types/YXmlText.js').YXmlText} YValueType
*/
/**
* @typedef {Object<string,any>|Array<any>|number|null|string|Uint8Array|BigInt|YValueType} YValue
*/
/**
* @typedef {import('../types/AbstractType.js').AbstractType<any,any>} YType
*/
/**
* @typedef {typeof import('../types/YArray.js').YArray<any>
* | typeof import('../types/YMap.js').YMap<any>
* | typeof import('../types/YText.js').YText<any>
* | typeof import('../types/YXmlFragment.js').YXmlFragment<any,any>
* | typeof import('../types/YXmlElement.js').YXmlElement<any,any>
* | typeof import('../types/YXmlHook.js').YXmlHook
* | typeof import('../types/YXmlText.js').YXmlText
* | typeof import('../types/AbstractType.js').AbstractType} YTypeConstructors
* @typedef {Object<string,any>|Array<any>|number|null|string|Uint8Array|BigInt|import('./').YType} YValue
*/

View File

@@ -33,8 +33,6 @@ import {
UpdateEncoderV1,
UpdateEncoderV2,
writeIdSet,
YXmlElement,
YXmlHook,
createIdSet
} from '../internals.js'
@@ -617,12 +615,8 @@ const createObfuscator = ({ formatting = true, subdocs = true, yxml = true } = {
case ContentType: {
if (yxml) {
const type = /** @type {ContentType} */ (content).type
if (type instanceof YXmlElement) {
type.nodeName = map.setIfUndefined(nodeNameCache, type.nodeName, () => 'node-' + i)
}
// @ts-ignore
if (type instanceof YXmlHook) {
type.hookName = map.setIfUndefined(nodeNameCache, type.hookName, () => 'hook-' + i)
if (type.name != null) {
type.name = map.setIfUndefined(nodeNameCache, type.nodeName, () => 'typename-' + i)
}
}
break

2065
src/ytype.js Normal file

File diff suppressed because it is too large Load Diff