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

Fix crashing differ on large paragraphs #16821

Merged
merged 6 commits into from
Aug 2, 2024
Merged

Fix crashing differ on large paragraphs #16821

merged 6 commits into from
Aug 2, 2024

Conversation

Mati365
Copy link
Member

@Mati365 Mati365 commented Jul 30, 2024

Suggested merge commit message (convention)

Fix (engine): No longer crash editor when trying to style a very long paragraph. Closes #16819


Additional information

It looks like 200k arguments, passed to .push method of the Array, causes Google Chrome crashing. I switched it to plain for loop and it works fine.

@Mati365 Mati365 changed the title Fix differ crashing on large paragraphs Fix crashing differ on large paragraphs Jul 30, 2024
Copy link
Contributor

@niegowski niegowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a helper like our spliceArray could be a better solution?

/**
* Splices one array into another. To be used instead of `Array.prototype.splice` as the latter may
* throw "Maximum call stack size exceeded" when passed huge number of items to insert.
*
* Note: in contrary to Array.splice, this function does not modify the original `target`.
*
* ```ts
* spliceArray( [ 1, 2 ], [ 3, 4 ], 0, 0 ); // [ 3, 4, 1, 2 ]
* spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 1 ); // [ 1, 3, 4 ]
* spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 0 ); // [ 1, 3, 4, 2 ]
* spliceArray( [ 1, 2 ], [ 3, 4 ], 2, 0 ); // [ 1, 2, 3, 4 ]
* spliceArray( [ 1, 2 ], [], 0, 1 ); // [ 2 ]
* ```
*
* @param target Array to be spliced.
* @param source Array of elements to be inserted to target.
* @param start Index at which nodes should be inserted/removed.
* @param count Number of items.
*
* @returns New spliced array.
*/
export default function spliceArray<T>( target: ReadonlyArray<T>, source: ReadonlyArray<T>, start: number, count: number ): Array<T> {

Copy link
Contributor

@pszczesniak pszczesniak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe extend the diff array size by change.howMany and use fill ??

@Mati365
Copy link
Member Author

Mati365 commented Jul 30, 2024

@pszczesniak / @niegowski I'd recommend sticking with a for loop to maintain consistency with other parts of _generateDiffInstructionsFromChanges. I don’t believe there will be any noticeable performance gains from optimizing this specific region, as it’s highly likely that it’s already JIT compiled to machine code.

edit: I checked .fill. Performance is identical.

diff.length = diff.length + change.howMany;
diff.fill( 'a', offset, diff.length );

Copy link
Contributor

@niegowski niegowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add an automatic test so we do not have a regression in the future.

@Mati365 Mati365 requested a review from niegowski August 2, 2024 11:44
@Mati365
Copy link
Member Author

Mati365 commented Aug 2, 2024

@niegowski Added

// add them manually one by one to avoid this limit. However loop might be a bit slower than `push` method on
// smaller changesets so we need to decide which method to use based on the size of the change.
// See: https://github.com/ckeditor/ckeditor5/issues/16819
if ( change.howMany > 1500 ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you write (here and/or in the issue) why we choose 1500?

It's based on some tests or it's some kind of random value?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Limitation of args stack depends on OS / Browser etc. I chose some kind of random value.

@niegowski niegowski merged commit 248d64c into master Aug 2, 2024
5 of 6 checks passed
@niegowski niegowski deleted the ck/16819 branch August 2, 2024 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Maximum call stack size exceeded error when trying to style a very long paragraph
3 participants