# MapperCache

class

Cache mechanism for [Mapper](module_engine_conversion_mapper-Mapper.md).

`MapperCache` improves performance for model-to-view position mapping, which is the main `Mapper` task. Asking for a mapping is much more frequent than actually performing changes, and even if the change happens, we can still partially keep the cache. This makes caching a useful strategy for `Mapper`.

`MapperCache` will store some data for view elements or view document fragments that are mapped by the `Mapper`. These view items are "tracked" by the `MapperCache`. For such view items, we will keep entries of model offsets inside their mapped counterpart. For the cached model offsets, we will keep a view position that is inside the tracked item. This allows us to either get the mapping instantly, or at least in less steps than when calculating it from the beginning.

Important problem related to caching is invalidating the cache. The cache must be invalidated each time the tracked view item changes. Additionally, we should invalidate as small part of the cache as possible. Since all the logic is encapsulated inside `MapperCache`, the `MapperCache` listens to view items [`change` event](module_engine_view_node-ViewNodeChangeEvent.md) and reacts to it. Then, it invalidates just the part of the cache that is "after" the changed part of the view.

As mentioned, `MapperCache` currently is used only for model-to-view position mapping as it was much bigger problem than view-to-model mapping. However, it should be possible to use it also for view-to-model.

The main assumptions regarding `MapperCache` are:

* it is an internal tool, used by `Mapper`, transparent to the outside (no additional effort when developing a plugin or a converter),
* it stores all the necessary data internally, which makes it easier to disable or debug,
* it is optimized for initial downcast process (long insertions), which is crucial for editor init and data save,
* it does not save all possible positions mapping for memory considerations, although it is a possible improvement, which may increase performance, as well as simplify some parts of the `MapperCache` logic.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L882)

<a id="properties">

## Properties

<a id="member-_cachedMapping">

### `_cachedMapping: WeakMap<ViewElement | ViewDocumentFragment, MappingCache>` _(private)_

For every view element or document fragment tracked by `MapperCache`, it holds currently cached data, or more precisely, model offset to view position mappings. See also `MappingCache` and `CacheItem`.

If an item is tracked by `MapperCache` it has an entry in this structure, so this structure can be used to check which items are tracked by `MapperCache`. When an item is no longer tracked, it is removed from this structure.

Although `MappingCache` and `CacheItem` structures allows for caching any model offsets and view positions, we only cache values for model offsets that are after a view node. So, in essence, positions inside text nodes are not cached. However, it takes from one to at most a few steps, to get from a cached position to a position that is inside a view text node.

Additionally, only one item per `modelOffset` is cached. There can be several view positions that map to the same `modelOffset`. Only the first save for `modelOffset` is stored.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L897)

<a id="member-_invalidateOnChildrenChangeCallback">

### `_invalidateOnChildrenChangeCallback: GetCallback<ViewNodeChangeEvent>` _(private)_

Callback fired whenever there is a direct or indirect children change in tracked view element or tracked view document fragment.

This is specified as a property to make it easier to set as an event callback and to later turn off that event.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L919)

<a id="member-_invalidateOnTextChangeCallback">

### `_invalidateOnTextChangeCallback: GetCallback<ViewNodeChangeEvent>` _(private)_

Callback fired whenever a view text node directly or indirectly inside a tracked view element or tracked view document fragment changes its text data.

This is specified as a property to make it easier to set as an event callback and to later turn off that event.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L930)

<a id="member-_nodeToCacheListIndex">

### `_nodeToCacheListIndex: WeakMap<ViewNode, number>` _(private)_

When `MapperCache` [saves](#function-save) view position -> model offset mapping, a `CacheItem` is inserted into certain `MappingCache#cacheList` at some index. Additionally, we store that index with the view node that is before the cached view position.

This allows to quickly get a cache list item related to certain view node, and hence, for fast cache invalidation.

For example, consider view: `<p>Some <strong>bold</strong> text.</p>`, where `<p>` is a view element tracked by `MapperCache`. If all `<p>` children were visited by `MapperCache`, then `<p>` cache list would have four items, related to following model offsets: `0`, `5`, `9`, `15`. Then, view node `"Some "` would have index `1`, `<strong>` index `2`, and `" text." index `3\`.

Note that the index related with a node is always greater than `0`. The first item in cache list is always for model offset `0` (and view offset `0`), and it is not related to any node.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L912)

<a id="methods">

## Methods

<a id="function-constructor">

### `constructor( args )` _(inherited)_

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-utils/src/mix.ts#L57)

#### Parameters

* `args: [ ]`

<a id="function-delegate">

### `delegate( events ) → EmitterMixinDelegateChain` _(inherited)_

Delegates selected events to another [`Emitter`](module_utils_emittermixin-Emitter.md). For instance:

```typescript
emitterA.delegate( 'eventX' ).to( emitterB );
emitterA.delegate( 'eventX', 'eventY' ).to( emitterC );
```

then `eventX` is delegated (fired by) `emitterB` and `emitterC` along with `data`:

```typescript
emitterA.fire( 'eventX', data );
```

and `eventY` is delegated (fired by) `emitterC` along with `data`:

```typescript
emitterA.fire( 'eventY', data );
```

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-utils/src/emittermixin.ts#L539)

#### Parameters

* `events: Array<string>`

  Event names that will be delegated to another emitter.

#### Returns

* `EmitterMixinDelegateChain`

<a id="function-fire">

### `fire( eventOrInfo, args ) → GetEventInfo<TEvent>[ 'return' ]` _(inherited)_

Fires an event, executing all callbacks registered for it.

The first parameter passed to callbacks is an [`EventInfo`](module_utils_eventinfo-EventInfo.md) object, followed by the optional `args` provided in the `fire()` method call.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-utils/src/emittermixin.ts#L512)

#### Type parameters

* `TEvent: extends BaseEvent`

  The type describing the event. See [`BaseEvent`](module_utils_emittermixin-BaseEvent.md).

#### Parameters

* `eventOrInfo: GetNameOrEventInfo<TEvent>`

  The name of the event or `EventInfo` object if event is delegated.

* `args: TEvent[ 'args' ]`

  Additional arguments to be passed to the callbacks.

#### Returns

* `GetEventInfo<TEvent>[ 'return' ]`

  By default the method returns `undefined`. However, the return value can be changed by listeners through modification of the [`evt.return`](module_utils_eventinfo-EventInfo.md#member-return)'s property (the event info is the first param of every callback).

<a id="function-getClosest">

### `getClosest( viewContainer, modelOffset ) → CacheItem`

For given `modelOffset` inside a model element mapped to given `viewContainer`, it returns the closest saved cache item (view position and related model offset) to the requested one.

It can be exactly the requested mapping, or it can be mapping that is the closest starting point to look for the requested mapping.

`viewContainer` must be a view element or document fragment that is mapped by the [Mapper](module_engine_conversion_mapper-Mapper.md).

If `viewContainer` is not yet tracked by the `MapperCache`, it will be automatically tracked after calling this method.

Note: this method will automatically "hoist" cached positions, i.e. it will return a position that is closest to the tracked element.

For example, if `<p>` is tracked element, and `^` is cached position:

```
<p>This is <strong>some <em>heavily <u>formatted</u>^</em></strong> text.</p>
```

If this position would be returned, instead, a position directly in `<p>` would be returned:

```
<p>This is <strong>some <em>heavily <u>formatted</u></em></strong>^ text.</p>
```

Note, that `modelOffset` for both positions is the same.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L1044)

#### Parameters

* `viewContainer: ViewElement | ViewDocumentFragment`

  Tracked view element or document fragment, which cache will be used.

* `modelOffset: number`

  Model offset in a model element or document fragment, which is mapped to `viewContainer`.

#### Returns

* `CacheItem`

<a id="function-listenTo:BASE_EMITTER">

### `listenTo( emitter, event, callback, options? ) → void` _(inherited)_

Registers a callback function to be executed when an event is fired in a specific (emitter) object.

Events can be grouped in namespaces using `:`. When namespaced event is fired, it additionally fires all callbacks for that namespace.

```typescript
// myEmitter.on( ... ) is a shorthand for myEmitter.listenTo( myEmitter, ... ).
myEmitter.on( 'myGroup', genericCallback );
myEmitter.on( 'myGroup:myEvent', specificCallback );

// genericCallback is fired.
myEmitter.fire( 'myGroup' );
// both genericCallback and specificCallback are fired.
myEmitter.fire( 'myGroup:myEvent' );
// genericCallback is fired even though there are no callbacks for "foo".
myEmitter.fire( 'myGroup:foo' );
```

An event callback can [stop the event](module_utils_eventinfo-EventInfo.md#member-stop) and set the [return value](module_utils_eventinfo-EventInfo.md#member-return) of the [`fire`](#function-fire) method.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-utils/src/emittermixin.ts#L475)

#### Type parameters

* `TEvent: extends BaseEvent`

  The type describing the event. See [`BaseEvent`](module_utils_emittermixin-BaseEvent.md).

#### Parameters

* `emitter: Emitter`

  The object that fires the event.

* `event: TEvent[ 'name' ]`

  The name of the event.

* `callback: GetCallback<TEvent>`

  The function to be called on event.

* `options?: GetCallbackOptions<TEvent>`

  Additional options.

#### Returns

* `void`

<a id="function-off">

### `off( event, callback ) → void` _(inherited)_

Stops executing the callback on the given event. Shorthand for [`this.stopListening( this, event, callback )`](#function-stopListening:BASE_STOP).

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-utils/src/emittermixin.ts#L444)

#### Parameters

* `event: string`

  The name of the event.

* `callback: Function`

  The function to stop being called.

#### Returns

* `void`

<a id="function-on">

### `on( event, callback, options? ) → void` _(inherited)_

Registers a callback function to be executed when an event is fired.

Shorthand for [`this.listenTo( this, event, callback, options )`](#function-listenTo:BASE_EMITTER) (it makes the emitter listen on itself).

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-utils/src/emittermixin.ts#L416)

#### Type parameters

* `TEvent: extends BaseEvent`

  The type descibing the event. See [`BaseEvent`](module_utils_emittermixin-BaseEvent.md).

#### Parameters

* `event: TEvent[ 'name' ]`

  The name of the event.

* `callback: GetCallback<TEvent>`

  The function to be called on event.

* `options?: GetCallbackOptions<TEvent>`

  Additional options.

#### Returns

* `void`

<a id="function-once">

### `once( event, callback, options? ) → void` _(inherited)_

Registers a callback function to be executed on the next time the event is fired only. This is similar to calling [`on`](#function-on) followed by [`off`](#function-off) in the callback.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-utils/src/emittermixin.ts#L431)

#### Type parameters

* `TEvent: extends BaseEvent`

  The type descibing the event. See [`BaseEvent`](module_utils_emittermixin-BaseEvent.md).

#### Parameters

* `event: TEvent[ 'name' ]`

  The name of the event.

* `callback: GetCallback<TEvent>`

  The function to be called on event.

* `options?: GetCallbackOptions<TEvent>`

  Additional options.

#### Returns

* `void`

<a id="function-save">

### `save( viewParent, viewOffset, viewContainer, modelOffset ) → void`

Saves cache for given view position mapping <-> model offset mapping. The view position should be after a node (i.e. it cannot be the first position inside its parent, or in other words, `viewOffset` must be greater than `0`).

Note, that if `modelOffset` for given `viewContainer` was already saved, the stored view position (i.e. parent+offset) will not be overwritten. However, it is important to still save it, as we still store additional data related to cached view positions.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L953)

#### Parameters

* `viewParent: ViewElement | ViewDocumentFragment`

  View position parent.

* `viewOffset: number`

  View position offset. Must be greater than `0`.

* `viewContainer: ViewElement | ViewDocumentFragment`

  Tracked view position ascendant (it may be the direct parent of the view position).

* `modelOffset: number`

  Model offset in the model element or document fragment which is mapped to `viewContainer`.

#### Returns

* `void`

<a id="function-startTracking">

### `startTracking( viewContainer ) → CacheItem`

Starts tracking given `viewContainer`, which must be mapped to a model element or model document fragment.

Note, that this method is automatically called by [`MapperCache#getClosest()`](#function-getClosest) and there is no need to call it manually.

This method initializes the cache for `viewContainer` and adds callbacks for [`change` event](module_engine_view_node-ViewNodeChangeEvent.md) fired by `viewContainer`. `MapperCache` listens to `change` event on the tracked elements to invalidate the stored cache.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L1080)

#### Parameters

* `viewContainer: ViewElement | ViewDocumentFragment`

#### Returns

* `CacheItem`

<a id="function-stopDelegating">

### `stopDelegating( event?, emitter? ) → void` _(inherited)_

Stops delegating events. It can be used at different levels:

* To stop delegating all events.
* To stop delegating a specific event to all emitters.
* To stop delegating a specific event to a specific emitter.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-utils/src/emittermixin.ts#L552)

#### Parameters

* `event?: string`

  The name of the event to stop delegating. If omitted, stops it all delegations.

* `emitter?: Emitter`

  (requires `event`) The object to stop delegating a particular event to. If omitted, stops delegation of `event` to all emitters.

#### Returns

* `void`

<a id="function-stopListening:BASE_STOP">

### `stopListening( emitter?, event?, callback? ) → void` _(inherited)_

Stops listening for events. It can be used at different levels:

* To stop listening to a specific callback.
* To stop listening to a specific event.
* To stop listening to all events fired by a specific object.
* To stop listening to all events fired by all objects.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-utils/src/emittermixin.ts#L497)

#### Parameters

* `emitter?: Emitter`

  The object to stop listening to. If omitted, stops it for all objects.

* `event?: string`

  (Requires the `emitter`) The name of the event to stop listening to. If omitted, stops it for all events from `emitter`.

* `callback?: Function`

  (Requires the `event`) The function to be removed from the call list for the given `event`.

#### Returns

* `void`

<a id="function-stopTracking">

### `stopTracking( viewContainer ) → void`

Stops tracking given `viewContainer`.

It removes the cached data and stops listening to [`change` event](module_engine_view_node-ViewNodeChangeEvent.md) on the `viewContainer`.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L1107)

#### Parameters

* `viewContainer: ViewElement | ViewDocumentFragment`

#### Returns

* `void`

<a id="function-_clearCacheAfter">

### `_clearCacheAfter( viewNode ) → void` _(private)_

Clears all the stored cache that is after given `viewNode`. The `viewNode` can be any node that is inside a tracked view element or view document fragment.

In reality, this function may clear a bit more cache than just "starting after" `viewNode`, but it is guaranteed that at least all cache after `viewNode` is invalidated.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L1163)

#### Parameters

* `viewNode: ViewNode`

#### Returns

* `void`

<a id="function-_clearCacheAll">

### `_clearCacheAll( viewContainer ) → void` _(private)_

Clears all the cache for given tracked `viewContainer`.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L1144)

#### Parameters

* `viewContainer: ViewElement | ViewDocumentFragment`

#### Returns

* `void`

<a id="function-_clearCacheFromCacheIndex">

### `_clearCacheFromCacheIndex( viewContainer, index ) → void` _(private)_

Clears all the cache in the cache list related to given `viewContainer`, starting from `index` (inclusive).

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L1204)

#### Parameters

* `viewContainer: ViewElement | ViewDocumentFragment`
* `index: number`

#### Returns

* `void`

<a id="function-_clearCacheInsideParent">

### `_clearCacheInsideParent( viewParent, index ) → void` _(private)_

Invalidates cache inside `viewParent`, starting from given `index` in that parent.

This method may clear a bit more cache than just what was saved after given `index`, but it is guaranteed that at least it will invalidate everything after `index`.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L1120)

#### Parameters

* `viewParent: ViewElement | ViewDocumentFragment`
* `index: number`

#### Returns

* `void`

<a id="function-_findInCacheList">

### `_findInCacheList( cacheList, offset ) → CacheItem` _(private)_

Finds a cache item in the given cache list, which `modelOffset` is closest (but smaller or equal) to given `offset`.

Since `cacheList` is a sorted array, this uses binary search to retrieve the item quickly.

[See source](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-engine/src/conversion/mapper.ts#L1242)

#### Parameters

* `cacheList: Array<CacheItem>`
* `offset: number`

#### Returns

* `CacheItem`

---

Full index of the CKEditor 5 API reference: [llms.txt](llms.txt)
