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

Commit 2592bf1

Browse files
author
Piotr Jasiun
authored
Merge pull request #1223 from ckeditor/t/1212
Other: Prevented `Writer` from usage outside of the `change` block. Closes #1212.
2 parents 9664b5d + 949e9df commit 2592bf1

File tree

2 files changed

+760
-384
lines changed

2 files changed

+760
-384
lines changed

src/model/writer.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ export default class Writer {
150150
* second parameter is a {@link module:engine/model/item~Item model item}.
151151
*/
152152
insert( item, itemOrPosition, offset ) {
153+
this._assertWriterUsageCorrectness();
154+
153155
const position = Position.createAt( itemOrPosition, offset );
154156

155157
// For text that has no parent we need to make a WeakInsert.
@@ -315,6 +317,8 @@ export default class Writer {
315317
* Model item or range on which the attribute will be set.
316318
*/
317319
setAttribute( key, value, itemOrRange ) {
320+
this._assertWriterUsageCorrectness();
321+
318322
if ( itemOrRange instanceof Range ) {
319323
setAttributeToRange( this, key, value, itemOrRange );
320324
} else {
@@ -350,6 +354,8 @@ export default class Writer {
350354
* Model item or range from which the attribute will be removed.
351355
*/
352356
removeAttribute( key, itemOrRange ) {
357+
this._assertWriterUsageCorrectness();
358+
353359
if ( itemOrRange instanceof Range ) {
354360
setAttributeToRange( this, key, null, itemOrRange );
355361
} else {
@@ -364,6 +370,8 @@ export default class Writer {
364370
* Model item or range from which all attributes will be removed.
365371
*/
366372
clearAttributes( itemOrRange ) {
373+
this._assertWriterUsageCorrectness();
374+
367375
const removeAttributesFromItem = item => {
368376
for ( const attribute of item.getAttributeKeys() ) {
369377
this.removeAttribute( attribute, item );
@@ -404,6 +412,8 @@ export default class Writer {
404412
* second parameter is a {@link module:engine/model/item~Item model item}.
405413
*/
406414
move( range, itemOrPosition, offset ) {
415+
this._assertWriterUsageCorrectness();
416+
407417
if ( !( range instanceof Range ) ) {
408418
/**
409419
* Invalid range to move.
@@ -448,6 +458,8 @@ export default class Writer {
448458
* @param {module:engine/model/item~Item|module:engine/model/range~Range} itemOrRange Model item or range to remove.
449459
*/
450460
remove( itemOrRange ) {
461+
this._assertWriterUsageCorrectness();
462+
451463
const addRemoveDelta = ( position, howMany ) => {
452464
const delta = new RemoveDelta();
453465
this.batch.addDelta( delta );
@@ -489,6 +501,8 @@ export default class Writer {
489501
* @param {module:engine/model/position~Position} position Position of merge.
490502
*/
491503
merge( position ) {
504+
this._assertWriterUsageCorrectness();
505+
492506
const delta = new MergeDelta();
493507
this.batch.addDelta( delta );
494508

@@ -542,6 +556,8 @@ export default class Writer {
542556
* @param {String} newName New element name.
543557
*/
544558
rename( element, newName ) {
559+
this._assertWriterUsageCorrectness();
560+
545561
if ( !( element instanceof Element ) ) {
546562
/**
547563
* Trying to rename an object which is not an instance of Element.
@@ -570,6 +586,8 @@ export default class Writer {
570586
* @param {module:engine/model/position~Position} position Position of split.
571587
*/
572588
split( position ) {
589+
this._assertWriterUsageCorrectness();
590+
573591
const delta = new SplitDelta();
574592
this.batch.addDelta( delta );
575593

@@ -616,6 +634,8 @@ export default class Writer {
616634
* @param {module:engine/model/element~Element|String} elementOrString Element or name of element to wrap the range with.
617635
*/
618636
wrap( range, elementOrString ) {
637+
this._assertWriterUsageCorrectness();
638+
619639
if ( !range.isFlat ) {
620640
/**
621641
* Range to wrap is not flat.
@@ -670,6 +690,8 @@ export default class Writer {
670690
* @param {module:engine/model/element~Element} element Element to unwrap.
671691
*/
672692
unwrap( element ) {
693+
this._assertWriterUsageCorrectness();
694+
673695
if ( element.parent === null ) {
674696
/**
675697
* Trying to unwrap an element which has no parent.
@@ -722,6 +744,8 @@ export default class Writer {
722744
* @param {module:engine/model/range~Range} [newRange] Marker range.
723745
*/
724746
setMarker( markerOrName, newRange ) {
747+
this._assertWriterUsageCorrectness();
748+
725749
const name = typeof markerOrName == 'string' ? markerOrName : markerOrName.name;
726750
const currentMarker = this.model.markers.get( name );
727751

@@ -752,6 +776,8 @@ export default class Writer {
752776
* @param {module:engine/model/markercollection~Marker|String} markerOrName Marker or marker name to remove.
753777
*/
754778
removeMarker( markerOrName ) {
779+
this._assertWriterUsageCorrectness();
780+
755781
const name = typeof markerOrName == 'string' ? markerOrName : markerOrName.name;
756782

757783
if ( !this.model.markers.has( name ) ) {
@@ -767,6 +793,23 @@ export default class Writer {
767793

768794
addMarkerOperation( this, name, oldRange, null );
769795
}
796+
797+
/**
798+
* Throws `writer-detached-writer-tries-to-modify-model` error when the writer is used outside of the `change()` block.
799+
*
800+
* @private
801+
*/
802+
_assertWriterUsageCorrectness() {
803+
/**
804+
* Detached writer tries to modify the model. Be sure, that your Writer is used
805+
* within the `model.change()` or `model.enqueueChange()` block.
806+
*
807+
* @error writer-detached-writer-tries-to-modify-model
808+
*/
809+
if ( this.model._currentWriter !== this ) {
810+
throw new CKEditorError( 'writer-detached-writer-tries-to-modify-model: Detached writer tries to modify the model.' );
811+
}
812+
}
770813
}
771814

772815
// Sets given attribute to each node in given range. When attribute value is null then attribute will be removed.

0 commit comments

Comments
 (0)