8
0
Просмотр исходного кода

Fixed: Editor crashed in some scenarios when mutations common ancestor could not be mapped to model.

Szymon Cofalik 8 лет назад
Родитель
Сommit
0515d19226
2 измененных файлов с 33 добавлено и 0 удалено
  1. 9 0
      packages/ckeditor5-typing/src/input.js
  2. 24 0
      packages/ckeditor5-typing/tests/input.js

+ 9 - 0
packages/ckeditor5-typing/src/input.js

@@ -197,6 +197,15 @@ class MutationHandler {
 		// Current model.
 		const currentModel = this.editor.editing.mapper.toModelElement( mutationsCommonAncestor );
 
+		// If common ancestor is not mapped, do not do anything. It probably is a parent of another view element.
+		// That means that we would need to diff model elements (see `if` below). Better return early instead of
+		// trying to get a reasonable model ancestor. It will fell into the `if` below anyway.
+		// This situation happens for example for lists. If `<ul>` is a common ancestor, `currentModel` is `undefined`
+		// because `<ul>` is not mapped (`<li>`s are).
+		if ( !currentModel ) {
+			return;
+		}
+
 		// Get children from both ancestors.
 		const modelFromDomChildren = Array.from( modelFromCurrentDom.getChildren() );
 		const currentModelChildren = Array.from( currentModel.getChildren() );

+ 24 - 0
packages/ckeditor5-typing/tests/input.js

@@ -445,6 +445,30 @@ describe( 'Input feature', () => {
 			expect( getModelData( model ) ).to.equal( '<paragraph>foobar   baz[]</paragraph>' );
 			expect( getViewData( view ) ).to.equal( '<p>foobar   baz{}</p>' );
 		} );
+
+		// ckeditor5#718.
+		it( 'should not crash and prevent all changes if view common ancestor of mutations cannot be mapped to model', () => {
+			editor.setData( '<p>Foo</p><ul><li>Bar</li><li>Baz</li></ul>' );
+
+			const ul = viewRoot.getChild( 1 );
+
+			viewDocument.fire( 'mutations', [
+				{
+					type: 'text',
+					oldText: 'Bar',
+					newText: 'Bx',
+					node: ul.getChild( 0 )
+				},
+				{
+					type: 'children',
+					oldChildren: [ ul.getChild( 0 ), ul.getChild( 1 ) ],
+					newChildren: [ ul.getChild( 0 ) ],
+					node: ul
+				}
+			] );
+
+			expect( getViewData( view ) ).to.equal( '<p>{}Foo</p><ul><li>Bar</li><li>Baz</li></ul>' );
+		} );
 	} );
 
 	describe( 'keystroke handling', () => {