nt.previousSibling.is( '$text' ) &&
								element.nextSibling && element.nextSibling.is( '$text' );
							if ( isBetweenTexts ) {
								tree.refreshTexts( position.parent );
							}
						}
						break;
					}
					case 'remove' : {
						if ( change.name === '$text' ) {
							// We have no information about which text nodes have been touched so
							// we refresh all of them (for simplicity).
							tree.refreshTexts( position.parent );
						} else {
							tree.remove( position );
						}
						break;
					}
					case 'attribute': {
						const walker = change.range.getWalker( { ignoreElementEnd: true } );
						let lastTextRefreshParent;

						for ( const { item } of walker ) {
							if ( item.is( 'element' ) ) {
								// If the walker is passing through an element, we just refresh it,
								// updating the attribute value in it (if it applies).
								tree.refreshNode( item );
							} else {
								// If instead we have a text node, we have no idea if it has been
								// merged with siblings, so we update it and all its sibling texts.
								if ( item.parent !== lastTextRefreshParent ) {
									tree.refreshTexts( item.parent );

									// Do it just once for this parent.
									lastTextRefreshParent = item.parent;
								}
							}
						}
					}
				}
			}

			/* istanbul ignore next */
			if ( process.env.NODE_ENV !== 'production' ) {
				if ( window.LOG_LIVE_MODEL_DATA ) {
					console.timeEnd( 'LiveModelData - process changes' );
				}
			}

			/**
			 * Fired when the `data` property value "potentially" changed.
			 *
			 * @memberOf {Model}
			 * @event #data
			 */
			document.model.fire( 'data' );
		} );
	}

	/**
	 * Gets the live object that holds the representation of the document main root data.
	 *
	 * This object must not be changed directly. It's main purpose is storage.
	 *
	 * return {Object} A live object.
	 */
	get() {
		return this.tree.root;
	}

	/**
	 * Sets the data of the main document root with data produced by get().
	 *
	 * @param data {Object} And objec