diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts index 562043609ea..ee05f8c53da 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts @@ -143,11 +143,12 @@ export class NotebookCellTextModel extends Disposable implements ICell { } spliceNotebookCellOutputs(splices: NotebookCellOutputsSplice[]): void { - splices.reverse().forEach(splice => { - this.outputs.splice(splice[0], splice[1], ...splice[2]); - }); - - this._onDidChangeOutputs.fire(splices); + if (splices.length > 0) { + splices.reverse().forEach(splice => { + this.outputs.splice(splice[0], splice[1], ...splice[2]); + }); + this._onDidChangeOutputs.fire(splices); + } } getEvaluatedMetadata(documentMetadata: NotebookDocumentMetadata): NotebookCellMetadata { diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 33de4d08c29..35e3e7ca5d1 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -735,6 +735,9 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } private _spliceNotebookCellOutputs(cellHandle: number, splices: NotebookCellOutputsSplice[], computeUndoRedo: boolean): void { + if (splices.length === 0) { + return; + } const cell = this._mapping.get(cellHandle); if (cell) { cell.spliceNotebookCellOutputs(splices); diff --git a/src/vs/workbench/contrib/notebook/test/notebookTextModel.test.ts b/src/vs/workbench/contrib/notebook/test/notebookTextModel.test.ts index 8c2f92a2228..9af7df52728 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookTextModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookTextModel.test.ts @@ -404,4 +404,74 @@ suite('NotebookTextModel', () => { assert.strictEqual(model.cells[0].outputs.length, 2); }); }); + + test('Clearing output of an empty notebook makes it dirty #119608', function () { + withTestNotebook([ + ['var a = 1;', 'javascript', CellKind.Code, [], { editable: true }], + ['var b = 2;', 'javascript', CellKind.Code, [], { editable: true }] + ], (editor) => { + const model = editor.viewModel.notebookDocument; + + let event: NotebookTextModelChangedEvent | undefined; + + model.onDidChangeContent(e => { event = e; }); + + { + // 1: add ouput -> event + const success = model.applyEdits( + [{ + editType: CellEditType.Output, index: 0, outputs: [ + { outputId: 'out1', outputs: [{ mime: 'application/x.notebook.stream', value: 1 }] } + ], + append: false + }], true, undefined, () => undefined, undefined, false + ); + + assert.ok(success); + assert.strictEqual(model.cells[0].outputs.length, 1); + assert.ok(event); + } + + { + // 2: clear all output w/ output -> event + event = undefined; + const success = model.applyEdits( + [{ + editType: CellEditType.Output, + index: 0, + outputs: [], + append: false + }, { + editType: CellEditType.Output, + index: 1, + outputs: [], + append: false + }], true, undefined, () => undefined, undefined, false + ); + assert.ok(success); + assert.ok(event); + } + + { + // 2: clear all output wo/ output -> NO event + event = undefined; + const success = model.applyEdits( + [{ + editType: CellEditType.Output, + index: 0, + outputs: [], + append: false + }, { + editType: CellEditType.Output, + index: 1, + outputs: [], + append: false + }], true, undefined, () => undefined, undefined, false + ); + + assert.ok(success); + assert.ok(event === undefined); + } + }); + }); });