Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table converters must not read model when converting to view #3281

Closed
scofalik opened this issue Aug 15, 2019 · 1 comment
Closed

Table converters must not read model when converting to view #3281

scofalik opened this issue Aug 15, 2019 · 1 comment
Labels
package:table type:bug This issue reports a buggy (incorrect) behavior.

Comments

@scofalik
Copy link
Contributor

One of the rules when creating converters is to perform view changes only depending on the view state and on the data passed by the dispatcher to the converter. It is incorrect to use the current model state when converting to view. Why? Because if there are multiple changes introduced in one batch, the model state is very different than the view state, so making decisions basing on data read from the model will lead to errors.

This didn't happen yet because tables weren't tested heavily in real-time collaboration, or, more importantly, in track changes.

One of the issues happens in the part of the code shown below. The change was to remove two rows, but one of them was heading so it also changed headingRows attribute.

export function downcastTableHeadingRowsChange( options = {} ) {
	// ... (cut for readibility)

	// The head section has shrunk so move rows from <thead> to <tbody>.
	// Filter out only those rows that are in wrong section.
	const rowsToMove = Array.from( table.getChildren() )
		.filter( ( { index } ) => isBetween( index, newRows - 1, oldRows ) )
		.reverse(); // The rows will be moved from <thead> to <tbody> in reverse order at the beginning of a <tbody>.

	const viewTableBody = getOrCreateTableSection( 'tbody', viewTable, conversionApi );
	moveViewRowsToTableSection( rowsToMove, viewTableBody, conversionApi, 0 );

	// Check if cells moved from <thead> to <tbody> requires renaming to <td> as this depends on current heading columns attribute.
	const tableWalker = new TableWalker( table, { startRow: newRows ? newRows - 1 : newRows, endRow: oldRows - 1 } );

	// ...
}

This is the headingRows attribute converter which is fired before remove rows converter. It uses the model to get view items which should be moved. But the rows that are supposed to be moved are not existing in the model anymore! rowsToMove contains wrong rows, which leads to weird stuff happening and ultimately into a crash.

@mlewand mlewand transferred this issue from ckeditor/ckeditor5-table Oct 9, 2019
@mlewand mlewand added this to the backlog milestone Oct 9, 2019
@mlewand mlewand added status:confirmed type:bug This issue reports a buggy (incorrect) behavior. package:table labels Oct 9, 2019
@jodator jodator removed this from the backlog milestone May 26, 2020
@jodator
Copy link
Contributor

jodator commented May 26, 2020

@scofalik this was a very good insight and we "fixed" that in recent iterations. Unfortunately this relates to #6506. The current "fix" uses beloved model.enqueChange() for the reasons described in #6506 and linked tickets.

This was fixed by #6437.

@jodator jodator closed this as completed May 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package:table type:bug This issue reports a buggy (incorrect) behavior.
Projects
None yet
Development

No branches or pull requests

3 participants