Code change:
This is a follow-up from and describes the problem that save participants causing a save operation
reproduced when undoing some fixes (applying the fix below)
fyi

Related discussion:
text: participant.dispose(); }); <del> test('Save Participant, calling save from within is unsupported but does not explode (sync save)', async function () { </del> <ins> test('Save Participant, calling save from within is unsupported but does not explode (sync save, no model change)', async function () { </ins> const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined); <del> await testSaveFromSaveParticipant(model, false); </del> <ins> await testSaveFromSaveParticipant(model, false, false, false); </ins> model.dispose(); }); <del> test('Save Participant, calling save from within is unsupported but does not explode (async save)', async function () { </del> <ins> test('Save Participant, calling save from within is unsupported but does not explode (async save, no model change)', async function () { </ins> const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined); <del> await testSaveFromSaveParticipant(model, true); </del> <ins> await testSaveFromSaveParticipant(model, true, false, false); </ins> model.dispose(); }); <del> async function testSaveFromSaveParticipant(model: TextFileEditorModel, async: boolean): Promise<void> { </del> <ins> test('Save Participant, calling save from within is unsupported but does not explode (sync save, model change)', async function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined); </ins> <del> let breakLoop = false; </del> <ins> await testSaveFromSaveParticipant(model, false, true, false); </ins> <del> const participant = accessor.textFileService.files.addSaveParticipant({ participate: async model => { if (breakLoop) { return; } </del> <ins> model.dispose(); }); test('Save Participant, calling save from within is unsupported but does not explode (async save, model change)', async function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined); await testSaveFromSaveParticipant(model, true, true, false); model.dispose(); }); test('Save Participant, calling save from within is unsupported but does not explode (force)', async function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined); await testSaveFromSaveParticipant(model, false, false, true); </ins> <del> breakLoop = true; </del> <ins> model.dispose(); }); async function testSaveFromSaveParticipant(model: TextFileEditorModel, async: boolean, modelChange: boolean, force: boolean): Promise<void> { const disposable = accessor.textFileService.files.addSaveParticipant({ participate: async () => { </ins> if (async) { await timeout(10); } <del> const newSavePromise = model.save(); // assert that this is the same promise as the outer one assert.strictEqual(savePromise, newSavePromise); </del> <ins> if (modelChange) { model.updateTextEditorModel(createTextBufferFactory('bar')); const newSavePromise = model.save(force ? { force } : undefined); // assert that this is not the same promise as the outer one assert.notStrictEqual(savePromise, newSavePromise); await newSavePromise; } else { const newSavePromise = model.save(force ? { force } : undefined); // assert that this is the same promise as the outer one assert.strictEqual(savePromise, newSavePromise); await savePromise; } </ins> } }); await model.resolve(); model.updateTextEditorModel(createTextBufferFactory('foo')); <del> const savePromise = model.save(); </del> <ins> const savePromise = model.save(force ? { force } : undefined); </ins> await savePromise; <del> participant.dispose(); </del> <ins> disposable.dispose(); </ins> } test('backup and restore (simple)', async function () {