From f36951d72a547b82f4f18d4d337ff90b0a77e2fa Mon Sep 17 00:00:00 2001 From: mohamedsalem401 Date: Tue, 2 Sep 2025 03:26:52 +0300 Subject: [PATCH] Fix race condition during storing project data --- packages/core/src/editor/model/Editor.ts | 28 +++++++++--------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/packages/core/src/editor/model/Editor.ts b/packages/core/src/editor/model/Editor.ts index 0878af20c..54c444194 100644 --- a/packages/core/src/editor/model/Editor.ts +++ b/packages/core/src/editor/model/Editor.ts @@ -412,7 +412,7 @@ export default class EditorModel extends Model { window.onbeforeunload = changes ? () => true : null; } - if (stm.isAutosave() && changes >= stm.getStepsBeforeSave()) { + if (stm.isAutosave() && changes >= stm.getStepsBeforeSave() && !this._isStoring) { this.store().catch((err) => this.logError(err)); } } @@ -462,15 +462,7 @@ export default class EditorModel extends Model { * */ handleUpdates(model: any, val: any, opt: any = {}) { // Component has been added temporarily - do not update storage or record changes - if ( - this.__skip || - this._isStoring || - !this.loadTriggered || - opt.temporary || - opt.noCount || - opt.avoidStore || - opt.partial - ) { + if (this.__skip || !this.loadTriggered || opt.temporary || opt.noCount || opt.avoidStore || opt.partial) { return; } @@ -878,17 +870,17 @@ export default class EditorModel extends Model { * @public */ async store(options?: T) { - if (this._isStoring) { - return; - } + if (this._isStoring) return; this._isStoring = true; - - const data = this.storeData(); - await this.Storage.store(data, options); - this.clearDirtyCount(); + // We use a 1ms timeout to defer the cleanup to the next tick of the event loop. + // This prevents a race condition where a store operation, like 'sync:content', + // might increase the dirty count before it can be properly cleared. setTimeout(() => { + this.clearDirtyCount(); this._isStoring = false; - }, 50); + }, 1); + const data = this.storeData(); + await this.Storage.store(data, options); return data; }