Skip to content

Commit 1b0816d

Browse files
authored
Merge branch 'main' into fix/improve-marker-placements
2 parents d457bdc + e3f691d commit 1b0816d

13 files changed

+92
-255
lines changed

src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,5 +1096,10 @@ configurationRegistry.registerConfiguration({
10961096
type: 'boolean',
10971097
default: true
10981098
},
1099+
[NotebookSetting.outputBackupSizeLimit]: {
1100+
markdownDescription: nls.localize('notebook.backup.sizeLimit', "The limit of notebook output size in kilobytes (KB) where notebook files will no longer be backed up for hot reload. Use 0 for unlimited."),
1101+
type: 'number',
1102+
default: 10000
1103+
}
10991104
}
11001105
});

src/vs/workbench/contrib/notebook/common/notebookCommon.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,7 @@ export const NotebookSetting = {
962962
notebookVariablesView: 'notebook.experimental.variablesView',
963963
InteractiveWindowPromptToSave: 'interactiveWindow.promptToSaveOnClose',
964964
cellFailureDiagnostics: 'notebook.cellFailureDiagnostics',
965+
outputBackupSizeLimit: 'notebook.backup.sizeLimit',
965966
} as const;
966967

967968
export const enum CellStatusbarAlignment {

src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no
2121
import { ICellDto2, INotebookEditorModel, INotebookLoadOptions, IResolvedNotebookEditorModel, NotebookCellsChangeType, NotebookData, NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
2222
import { INotebookSerializer, INotebookService, SimpleNotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookService';
2323
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
24-
import { IFileWorkingCopyModelConfiguration } from 'vs/workbench/services/workingCopy/common/fileWorkingCopy';
24+
import { IFileWorkingCopyModelConfiguration, SnapshotContext } from 'vs/workbench/services/workingCopy/common/fileWorkingCopy';
2525
import { IFileWorkingCopyManager } from 'vs/workbench/services/workingCopy/common/fileWorkingCopyManager';
2626
import { IStoredFileWorkingCopy, IStoredFileWorkingCopyModel, IStoredFileWorkingCopyModelContentChangedEvent, IStoredFileWorkingCopyModelFactory, IStoredFileWorkingCopySaveEvent, StoredFileWorkingCopyState } from 'vs/workbench/services/workingCopy/common/storedFileWorkingCopy';
2727
import { IUntitledFileWorkingCopy, IUntitledFileWorkingCopyModel, IUntitledFileWorkingCopyModelContentChangedEvent, IUntitledFileWorkingCopyModelFactory } from 'vs/workbench/services/workingCopy/common/untitledFileWorkingCopy';
@@ -252,14 +252,15 @@ export class NotebookFileWorkingCopyModel extends Disposable implements IStoredF
252252
return this._notebookModel;
253253
}
254254

255-
async snapshot(token: CancellationToken): Promise<VSBufferReadableStream> {
255+
async snapshot(context: SnapshotContext, token: CancellationToken): Promise<VSBufferReadableStream> {
256256
const serializer = await this.getNotebookSerializer();
257257

258258
const data: NotebookData = {
259259
metadata: filter(this._notebookModel.metadata, key => !serializer.options.transientDocumentMetadata[key]),
260260
cells: [],
261261
};
262262

263+
let outputSize = 0;
263264
for (const cell of this._notebookModel.cells) {
264265
const cellData: ICellDto2 = {
265266
cellKind: cell.cellKind,
@@ -270,6 +271,18 @@ export class NotebookFileWorkingCopyModel extends Disposable implements IStoredF
270271
internalMetadata: cell.internalMetadata
271272
};
272273

274+
const outputSizeLimit = this._configurationService.getValue<number>(NotebookSetting.outputBackupSizeLimit) * 1024;
275+
if (context === SnapshotContext.Backup && outputSizeLimit > 0) {
276+
cell.outputs.forEach(output => {
277+
output.outputs.forEach(item => {
278+
outputSize += item.data.byteLength;
279+
});
280+
});
281+
if (outputSize > outputSizeLimit) {
282+
throw new Error('Notebook too large to backup');
283+
}
284+
}
285+
273286
cellData.outputs = !serializer.options.transientOutputs ? cell.outputs : [];
274287
cellData.metadata = filter(cell.metadata, key => !serializer.options.transientCellMetadata[key]);
275288

src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
1515
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
1616
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
1717
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
18-
import { CellKind, NotebookData, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
18+
import { CellKind, IOutputDto, NotebookData, NotebookSetting, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
1919
import { NotebookFileWorkingCopyModel } from 'vs/workbench/contrib/notebook/common/notebookEditorModel';
2020
import { INotebookSerializer, INotebookService, SimpleNotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookService';
2121
import { setupInstantiationService } from 'vs/workbench/contrib/notebook/test/browser/testNotebookEditor';
22+
import { SnapshotContext } from 'vs/workbench/services/workingCopy/common/fileWorkingCopy';
2223

2324
suite('NotebookFileWorkingCopyModel', function () {
2425

@@ -63,7 +64,7 @@ suite('NotebookFileWorkingCopyModel', function () {
6364
configurationService
6465
));
6566

66-
await model.snapshot(CancellationToken.None);
67+
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
6768
assert.strictEqual(callCount, 1);
6869
}
6970

@@ -84,7 +85,7 @@ suite('NotebookFileWorkingCopyModel', function () {
8485
),
8586
configurationService
8687
));
87-
await model.snapshot(CancellationToken.None);
88+
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
8889
assert.strictEqual(callCount, 1);
8990
}
9091
});
@@ -119,7 +120,7 @@ suite('NotebookFileWorkingCopyModel', function () {
119120
configurationService
120121
));
121122

122-
await model.snapshot(CancellationToken.None);
123+
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
123124
assert.strictEqual(callCount, 1);
124125
}
125126

@@ -140,7 +141,7 @@ suite('NotebookFileWorkingCopyModel', function () {
140141
),
141142
configurationService
142143
));
143-
await model.snapshot(CancellationToken.None);
144+
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
144145
assert.strictEqual(callCount, 1);
145146
}
146147
});
@@ -174,7 +175,7 @@ suite('NotebookFileWorkingCopyModel', function () {
174175
configurationService
175176
));
176177

177-
await model.snapshot(CancellationToken.None);
178+
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
178179
assert.strictEqual(callCount, 1);
179180
}
180181

@@ -195,10 +196,52 @@ suite('NotebookFileWorkingCopyModel', function () {
195196
),
196197
configurationService
197198
));
198-
await model.snapshot(CancellationToken.None);
199+
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
199200
assert.strictEqual(callCount, 1);
200201
}
201202
});
203+
204+
test('Notebooks with outputs beyond the size threshold will throw for backup snapshots', async function () {
205+
const outputLimit = 100;
206+
await configurationService.setUserConfiguration(NotebookSetting.outputBackupSizeLimit, outputLimit * 1.0 / 1024);
207+
const largeOutput: IOutputDto = { outputId: '123', outputs: [{ mime: Mimes.text, data: VSBuffer.fromString('a'.repeat(outputLimit + 1)) }] };
208+
const notebook = instantiationService.createInstance(NotebookTextModel,
209+
'notebook',
210+
URI.file('test'),
211+
[{ cellKind: CellKind.Code, language: 'foo', mime: 'foo', source: 'foo', outputs: [largeOutput], metadata: { foo: 123, bar: 456 } }],
212+
{},
213+
{ transientCellMetadata: {}, transientDocumentMetadata: {}, cellContentMetadata: {}, transientOutputs: false, }
214+
);
215+
disposables.add(notebook);
216+
217+
let callCount = 0;
218+
const model = disposables.add(new NotebookFileWorkingCopyModel(
219+
notebook,
220+
mockNotebookService(notebook,
221+
new class extends mock<INotebookSerializer>() {
222+
override options: TransientOptions = { transientOutputs: true, transientDocumentMetadata: {}, transientCellMetadata: { bar: true }, cellContentMetadata: {} };
223+
override async notebookToData(notebook: NotebookData) {
224+
callCount += 1;
225+
assert.strictEqual(notebook.cells[0].metadata!.foo, 123);
226+
assert.strictEqual(notebook.cells[0].metadata!.bar, undefined);
227+
return VSBuffer.fromString('');
228+
}
229+
}
230+
),
231+
configurationService
232+
));
233+
234+
try {
235+
await model.snapshot(SnapshotContext.Backup, CancellationToken.None);
236+
assert.fail('Expected snapshot to throw an error for large output');
237+
} catch (e) {
238+
assert.notEqual(e.code, 'ERR_ASSERTION', e.message);
239+
}
240+
241+
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
242+
assert.strictEqual(callCount, 1);
243+
244+
});
202245
});
203246

204247
function mockNotebookService(notebook: NotebookTextModel, notebookSerializer: INotebookSerializer) {

src/vs/workbench/contrib/terminal/browser/terminalActions.ts

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { Action2, registerAction2, IAction2Options, MenuId } from 'vs/platform/a
2020
import { ICommandService } from 'vs/platform/commands/common/commands';
2121
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
2222
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
23-
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
23+
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
2424
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
2525
import { ILabelService } from 'vs/platform/label/common/label';
2626
import { IListService } from 'vs/platform/list/browser/listService';
@@ -64,8 +64,6 @@ import { AccessibleViewProviderId, accessibleViewCurrentProviderId, accessibleVi
6464
import { isKeyboardEvent, isMouseEvent, isPointerEvent } from 'vs/base/browser/dom';
6565
import { editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
6666
import { InstanceContext } from 'vs/workbench/contrib/terminal/browser/terminalContextMenu';
67-
import { TerminalVoiceSession } from 'vs/workbench/contrib/terminal/browser/terminalVoice';
68-
import { HasSpeechProvider } from 'vs/workbench/contrib/speech/common/speechService';
6967

7068
export const switchTerminalActionViewItemSeparator = '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500';
7169
export const switchTerminalShowTabsTitle = localize('showTerminalTabs', "Show Tabs");
@@ -1661,28 +1659,6 @@ export function registerTerminalActions() {
16611659
}
16621660
}
16631661
});
1664-
1665-
registerActiveInstanceAction({
1666-
id: TerminalCommandId.StartVoice,
1667-
title: localize2('workbench.action.terminal.startDictation', "Start Dictation in Terminal"),
1668-
precondition: ContextKeyExpr.and(HasSpeechProvider, sharedWhenClause.terminalAvailable),
1669-
f1: true,
1670-
run: (activeInstance, c, accessor) => {
1671-
const instantiationService = accessor.get(IInstantiationService);
1672-
TerminalVoiceSession.getInstance(instantiationService).start();
1673-
}
1674-
});
1675-
1676-
registerActiveInstanceAction({
1677-
id: TerminalCommandId.StopVoice,
1678-
title: localize2('workbench.action.terminal.stopDictation', "Stop Dictation in Terminal"),
1679-
precondition: ContextKeyExpr.and(HasSpeechProvider, sharedWhenClause.terminalAvailable),
1680-
f1: true,
1681-
run: (activeInstance, c, accessor) => {
1682-
const instantiationService = accessor.get(IInstantiationService);
1683-
TerminalVoiceSession.getInstance(instantiationService).stop(true);
1684-
}
1685-
});
16861662
}
16871663

16881664
interface IRemoteTerminalPick extends IQuickPickItem {

0 commit comments

Comments
 (0)