Explorar el Código

Feature: Introduced `conversion.Mapper#flushUnboundMarkers`.

Szymon Cofalik hace 6 años
padre
commit
61c970408b

+ 1 - 3
packages/ckeditor5-engine/src/conversion/downcastdispatcher.js

@@ -143,15 +143,13 @@ export default class DowncastDispatcher {
 			}
 		}
 
-		for ( const markerName of this.conversionApi.mapper._unboundMarkers ) {
+		for ( const markerName of this.conversionApi.mapper.flushUnboundMarkerNames() ) {
 			const markerRange = markers.get( markerName ).getRange();
 
 			this.convertMarkerRemove( markerName, markerRange, writer );
 			this.convertMarkerAdd( markerName, markerRange, writer );
 		}
 
-		this.conversionApi.mapper._unboundMarkers.clear();
-
 		// After the view is updated, convert markers which have changed.
 		for ( const change of differ.getMarkersToAdd() ) {
 			this.convertMarkerAdd( change.name, change.range, writer );

+ 30 - 18
packages/ckeditor5-engine/src/conversion/mapper.js

@@ -88,13 +88,13 @@ export default class Mapper {
 		this._elementToMarkerNames = new Map();
 
 		/**
-		 * Stores markers which has changed due to unbinding a view element (so it is assumed that the view element has been removed,
-		 * moved or renamed). In some cases such markers need to be refreshed (re-rendered).
+		 * Stores marker names of markers which has changed due to unbinding a view element (so it is assumed that the view element
+		 * has been removed, moved or renamed).
 		 *
-		 * @protected
+		 * @private
 		 * @member {Set.<module:engine/model/markercollection~Marker>}
 		 */
-		this._unboundMarkers = new Set();
+		this._unboundMarkerNames = new Set();
 
 		// Default mapper algorithm for mapping model position to view position.
 		this.on( 'modelToViewPosition', ( evt, data ) => {
@@ -153,7 +153,7 @@ export default class Mapper {
 
 		if ( this._elementToMarkerNames.has( viewElement ) ) {
 			for ( const markerName of this._elementToMarkerNames.get( viewElement ) ) {
-				this._unboundMarkers.add( markerName );
+				this._unboundMarkerNames.add( markerName );
 			}
 		}
 
@@ -208,30 +208,42 @@ export default class Mapper {
 	 * @param {String} name Marker name.
 	 */
 	unbindElementFromMarkerName( element, name ) {
-		const elements = this._markerNameToElements.get( name );
-
-		if ( !elements ) {
-			return;
-		}
+		const nameToElements = this._markerNameToElements.get( name );
 
-		elements.delete( element );
+		if ( nameToElements ) {
+			nameToElements.delete( element );
 
-		if ( elements.size == 0 ) {
-			this._markerNameToElements.delete( name );
+			if ( nameToElements.size == 0 ) {
+				this._markerNameToElements.delete( name );
+			}
 		}
 
-		const names = this._elementToMarkerNames.get( element );
+		const elementToNames = this._elementToMarkerNames.get( element );
 
-		if ( names ) {
-			names.delete( name );
+		if ( elementToNames ) {
+			elementToNames.delete( name );
 
-			if ( names.size == 0 ) {
+			if ( elementToNames.size == 0 ) {
 				this._elementToMarkerNames.delete( element );
 			}
 		}
 	}
 
 	/**
+	 * Returns all marker names of markers which has changed due to unbinding a view element (so it is assumed that the view element
+	 * has been removed, moved or renamed) since the last flush. After returning, the marker names list is cleared.
+	 *
+	 * @returns {Array.<String>}
+	 */
+	flushUnboundMarkerNames() {
+		const markerNames = Array.from( this._unboundMarkerNames );
+
+		this._unboundMarkerNames.clear();
+
+		return markerNames;
+	}
+
+	/**
 	 * Removes all model to view and view to model bindings.
 	 */
 	clearBindings() {
@@ -239,7 +251,7 @@ export default class Mapper {
 		this._viewToModelMapping = new WeakMap();
 		this._markerNameToElements = new Map();
 		this._elementToMarkerNames = new Map();
-		this._unboundMarkers = new Set();
+		this._unboundMarkerNames = new Set();
 	}
 
 	/**

+ 24 - 18
packages/ckeditor5-engine/tests/conversion/mapper.js

@@ -52,8 +52,6 @@ describe( 'Mapper', () => {
 			expect( Array.from( mapper.markerNameToElements( 'foo' ) ) ).to.deep.equal( [ viewA, viewD ] );
 
 			mapper.unbindViewElement( viewD );
-			expect( Array.from( mapper._unboundMarkers ) ).to.deep.equal( [ 'foo', 'bar' ] );
-
 			mapper.clearBindings();
 
 			expect( mapper.toModelElement( viewA ) ).to.be.undefined;
@@ -65,7 +63,7 @@ describe( 'Mapper', () => {
 			expect( mapper.toViewElement( modelC ) ).to.be.undefined;
 
 			expect( mapper.markerNameToElements( 'foo' ) ).to.be.null;
-			expect( Array.from( mapper._unboundMarkers ) ).to.deep.equal( [] );
+			expect( mapper.flushUnboundMarkerNames() ).to.deep.equal( [] );
 		} );
 	} );
 
@@ -139,21 +137,6 @@ describe( 'Mapper', () => {
 			expect( mapper.toModelElement( viewA ) ).to.be.undefined;
 			expect( mapper.toViewElement( modelA ) ).to.equal( viewB );
 		} );
-
-		it( 'should add marker names to _unboundMarkers set', () => {
-			const viewA = new ViewElement( 'a' );
-			const modelA = new ModelElement( 'a' );
-
-			const mapper = new Mapper();
-			mapper.bindElements( modelA, viewA );
-
-			mapper.bindElementToMarker( viewA, 'foo' );
-			mapper.bindElementToMarker( viewA, 'bar' );
-
-			mapper.unbindViewElement( viewA );
-
-			expect( Array.from( mapper._unboundMarkers ) ).to.deep.equal( [ 'foo', 'bar' ] );
-		} );
 	} );
 
 	describe( 'Standard mapping', () => {
@@ -784,4 +767,27 @@ describe( 'Mapper', () => {
 			expect( viewMappedAncestor ).to.equal( viewP );
 		} );
 	} );
+
+	describe( 'flushUnboundMarkerNames()', () => {
+		it( 'should return marker names of markers which elements has been unbound and clear that list', () => {
+			const viewA = new ViewElement( 'a' );
+			const viewB = new ViewElement( 'b' );
+
+			const mapper = new Mapper();
+
+			mapper.bindElementToMarker( viewA, 'foo' );
+			mapper.bindElementToMarker( viewA, 'bar' );
+			mapper.bindElementToMarker( viewB, 'bar' );
+
+			mapper.unbindViewElement( viewA );
+
+			expect( mapper.flushUnboundMarkerNames() ).to.deep.equal( [ 'foo', 'bar' ] );
+			expect( mapper.flushUnboundMarkerNames() ).to.deep.equal( [] );
+
+			mapper.unbindViewElement( viewB );
+
+			expect( mapper.flushUnboundMarkerNames() ).to.deep.equal( [ 'bar' ] );
+			expect( mapper.flushUnboundMarkerNames() ).to.deep.equal( [] );
+		} );
+	} );
 } );