@@ -139,11 +139,18 @@ export function useDomEditCommits({
139139 const reportedUnresolvableRef = useRef ( new Set < string > ( ) ) ;
140140
141141 // fallow-ignore-next-line complexity
142- const performPersistDomEditOperations : PersistDomEditOperations = useCallback (
142+ const performPersistDomEditOperations = useCallback (
143143 // fallow-ignore-next-line complexity
144- async ( selection , operations , options ) => {
145- const pid = projectIdRef . current ;
146- if ( ! pid ) throw new Error ( "No active project" ) ;
144+ async (
145+ selection : DomEditSelection ,
146+ operations : PatchOperation [ ] ,
147+ options : Parameters < PersistDomEditOperations > [ 2 ] ,
148+ expectedProjectId : string ,
149+ ) => {
150+ if ( projectIdRef . current !== expectedProjectId ) {
151+ throw new Error ( "Active project changed before the edit could be saved" ) ;
152+ }
153+ const pid = expectedProjectId ;
147154 if ( options ?. shouldSave && ! options . shouldSave ( ) ) return ;
148155
149156 const targetPath = selection . sourceFile || activeCompPath || "index.html" ;
@@ -160,6 +167,10 @@ export function useDomEditCommits({
160167 throw new Error ( `Missing file contents for ${ targetPath } ` ) ;
161168 }
162169
170+ if ( projectIdRef . current !== expectedProjectId ) {
171+ throw new Error ( "Active project changed before the edit could be saved" ) ;
172+ }
173+
163174 if ( options ?. shouldSave && ! options . shouldSave ( ) ) return ;
164175
165176 // Validate layout values BEFORE any persist path runs. The SDK cutover
@@ -298,20 +309,29 @@ export function useDomEditCommits({
298309 ) ;
299310
300311 const persistDomEditOperations : PersistDomEditOperations = useCallback (
301- ( selection , operations , options ) =>
302- queueDomEditSave ( ( ) => performPersistDomEditOperations ( selection , operations , options ) ) ,
303- [ performPersistDomEditOperations , queueDomEditSave ] ,
312+ ( selection , operations , options ) => {
313+ const expectedProjectId = projectIdRef . current ;
314+ if ( ! expectedProjectId ) return Promise . reject ( new Error ( "No active project" ) ) ;
315+ return queueDomEditSave ( ( ) =>
316+ performPersistDomEditOperations ( selection , operations , options , expectedProjectId ) ,
317+ ) ;
318+ } ,
319+ [ performPersistDomEditOperations , projectIdRef , queueDomEditSave ] ,
304320 ) ;
305321
306322 const commitDomEditPatchBatches : CommitDomEditPatchBatches = useCallback (
307- ( batches , options ) =>
308- queueDomEditSave (
323+ ( batches , options ) => {
324+ const expectedProjectId = projectIdRef . current ;
325+ if ( ! expectedProjectId ) return Promise . reject ( new Error ( "No active project" ) ) ;
326+ return queueDomEditSave (
309327 // One queued transaction owns validation, persistence, history, reload,
310328 // and its durable result; splitting those phases risks partial commits.
311329 // fallow-ignore-next-line complexity
312330 async ( ) => {
313- const pid = projectIdRef . current ;
314- if ( ! pid ) throw new Error ( "No active project" ) ;
331+ if ( projectIdRef . current !== expectedProjectId ) {
332+ throw new Error ( "Active project changed before the edit could be saved" ) ;
333+ }
334+ const pid = expectedProjectId ;
315335 const unsafeFields = batches . flatMap ( ( batch ) =>
316336 batch . patches . flatMap ( ( patch ) => findUnsafeDomPatchValues ( patch ) ) ,
317337 ) ;
@@ -373,7 +393,8 @@ export function useDomEditCommits({
373393 label : options . label ,
374394 } ) ;
375395 throw error ;
376- } ) ,
396+ } ) ;
397+ } ,
377398 [
378399 domEditSaveTimestampRef ,
379400 editHistory ,
0 commit comments