Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit e1c2a7d

Browse files
committed
Changed: Fixed detaching model.LiveRange in model.LiveSelection.
1 parent 3a8ebed commit e1c2a7d

File tree

2 files changed

+51
-8
lines changed

2 files changed

+51
-8
lines changed

src/model/liveselection.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ export default class LiveSelection extends Selection {
116116
* Unbinds all events previously bound by document selection.
117117
*/
118118
destroy() {
119-
for ( let i = 0; i < this._ranges.length; i++ ) {
120-
this._ranges[ i ].detach();
119+
while ( this._ranges.length ) {
120+
this._popRange();
121121
}
122122

123123
this.stopListening();
@@ -255,7 +255,19 @@ export default class LiveSelection extends Selection {
255255
* @inheritDoc
256256
*/
257257
_popRange() {
258-
this._ranges.pop().detach();
258+
this._removeRangeAtIndex( this._ranges.length - 1 );
259+
}
260+
261+
/**
262+
* Removes a range from `LiveSelection` and detaches it.
263+
*
264+
* @private
265+
* @params {Number} index Index from which a range should be removed.
266+
*/
267+
_removeRangeAtIndex( index ) {
268+
const range = this._ranges.splice( index, 1 )[ 0 ];
269+
270+
range.detach();
259271
}
260272

261273
/**
@@ -302,7 +314,8 @@ export default class LiveSelection extends Selection {
302314
this._checkRange( range );
303315

304316
const liveRange = LiveRange.createFromRange( range );
305-
this.listenTo( liveRange, 'change', ( evt, oldRange ) => {
317+
318+
liveRange.on( 'change', ( evt, oldRange ) => {
306319
if ( liveRange.root == this._document.graveyard ) {
307320
this._fixGraveyardSelection( liveRange, oldRange );
308321
}
@@ -638,8 +651,11 @@ export default class LiveSelection extends Selection {
638651

639652
const newRange = this._prepareRange( selectionRange );
640653
const index = this._ranges.indexOf( gyRange );
641-
gyRange.detach();
642654

655+
// Remove incorrect range.
656+
this._removeRangeAtIndex( index );
657+
658+
// Splice in correct range.
643659
this._ranges.splice( index, 1, newRange );
644660
}
645661
}

tests/model/liveselection.js

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,21 @@ describe( 'LiveSelection', () => {
171171
selection.addRange( liveRange );
172172
selection.addRange( range );
173173

174-
const ranges = selection._ranges;
174+
const ranges = Array.from( selection._ranges );
175175

176176
sinon.spy( ranges[ 0 ], 'detach' );
177177
sinon.spy( ranges[ 1 ], 'detach' );
178178

179+
sinon.spy( selection, 'stopListening' );
180+
179181
selection.destroy();
180182

181183
expect( ranges[ 0 ].detach.called ).to.be.true;
182184
expect( ranges[ 1 ].detach.called ).to.be.true;
183185

186+
expect( selection.stopListening.calledWith( ranges[ 0 ] ) ).to.be.true;
187+
expect( selection.stopListening.calledWith( ranges[ 1 ] ) ).to.be.true;
188+
184189
ranges[ 0 ].detach.restore();
185190
ranges[ 1 ].detach.restore();
186191
} );
@@ -226,6 +231,7 @@ describe( 'LiveSelection', () => {
226231
sinon.spy( ranges[ 0 ], 'detach' );
227232
sinon.spy( ranges[ 1 ], 'detach' );
228233

234+
sinon.spy( selection, 'stopListening' );
229235
selection.removeAllRanges();
230236
} );
231237

@@ -240,7 +246,7 @@ describe( 'LiveSelection', () => {
240246
expect( selection.focus.isEqual( new Position( root, [ 0, 0 ] ) ) ).to.be.true;
241247
} );
242248

243-
it( 'should detach ranges', () => {
249+
it( 'should detach ranges and stop listening to removed ranges', () => {
244250
expect( ranges[ 0 ].detach.called ).to.be.true;
245251
expect( ranges[ 1 ].detach.called ).to.be.true;
246252
} );
@@ -261,7 +267,7 @@ describe( 'LiveSelection', () => {
261267
} ).to.throw( CKEditorError, /model-selection-added-not-range/ );
262268
} );
263269

264-
it( 'should detach removed ranges', () => {
270+
it( 'should detach and stop listening to removed ranges', () => {
265271
selection.addRange( liveRange );
266272
selection.addRange( range );
267273

@@ -270,6 +276,8 @@ describe( 'LiveSelection', () => {
270276
sinon.spy( oldRanges[ 0 ], 'detach' );
271277
sinon.spy( oldRanges[ 1 ], 'detach' );
272278

279+
sinon.spy( selection, 'stopListening' );
280+
273281
selection.setRanges( [] );
274282

275283
expect( oldRanges[ 0 ].detach.called ).to.be.true;
@@ -599,6 +607,25 @@ describe( 'LiveSelection', () => {
599607

600608
expect( selection.getFirstPosition().path ).to.deep.equal( [ 0, 6 ] );
601609
} );
610+
611+
it( 'detach and stop listening to a range that ended up in in graveyard', () => {
612+
selection.collapse( new Position( root, [ 1, 3 ] ) );
613+
614+
const range = selection._ranges[ 0 ];
615+
616+
sinon.spy( range, 'detach' );
617+
sinon.spy( selection, 'stopListening' );
618+
619+
doc.applyOperation( wrapInDelta(
620+
new RemoveOperation(
621+
new Position( root, [ 1, 2 ] ),
622+
2,
623+
doc.version
624+
)
625+
) );
626+
627+
expect( range.detach.called ).to.be.true;
628+
} );
602629
} );
603630
} );
604631

0 commit comments

Comments
 (0)