There is a bug in Safari. When we call blocks.render() it leads the onChange call.
Explanation
The blocks.render()contains a mutation observer mutex:
/**
* Fills Editor with Blocks data
*
* @param {OutputData} data — Saved Editor data
*/
public async render(data: OutputData): Promise<void> {
// ...
this.Editor.ModificationsObserver.disable();
await this.Editor.BlockManager.clear();
await this.Editor.Renderer.render(data.blocks);
this.Editor.ModificationsObserver.enable();
}
But the Paragraph's render creates a DOM and inserts a text using requestAnimationFrame — so text inserted in some time after render. It leads the onChange call since Block's DOM is changed.
Bug happened only in Safari, because Renderer.render() promise resolves in the requestIdleCallback (which happened after requestAnimationFrame), but Safari does not support it, and it uses polypill (working on setTimeout) instead, so promise resolves before Paragraph Dom mutation.
Solution
The first and simplest solution was to wrap this.Editor.ModificationsObserver.enable(); into requestAnimationFrame as well.
But more right way is to remove requestAnimationFrame from Paragraph render since it has no sense — it leads 2 layouts instead of one. For performance reason, it's important to not to call drawView in a constructor, but render can put a text without RaF
This PR introduces two changes:
requestAnimationFrame
call on renderThe problem
There is a bug in Safari. When we call
blocks.render()
it leads theonChange
call.Explanation
The
blocks.render()
contains a mutation observer mutex:But the
Paragraph
's render creates a DOM and inserts a text usingrequestAnimationFrame
— so text inserted in some time after render. It leads theonChange
call since Block's DOM is changed.Bug happened only in Safari, because
Renderer.render()
promise resolves in therequestIdleCallback
(which happened afterrequestAnimationFrame
), but Safari does not support it, and it uses polypill (working on setTimeout) instead, so promise resolves before Paragraph Dom mutation.Solution
The first and simplest solution was to wrap
this.Editor.ModificationsObserver.enable();
intorequestAnimationFrame
as well.But more right way is to remove
requestAnimationFrame
from Paragraph render since it has no sense — it leads 2 layouts instead of one. For performance reason, it's important to not to calldrawView
in a constructor, butrender
can put a text withoutRaF