Skip to content

Commit fbd39c1

Browse files
committed
moved optimization to model
1 parent 4aa165c commit fbd39c1

File tree

4 files changed

+91
-43
lines changed

4 files changed

+91
-43
lines changed

src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,15 +1413,11 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {
14131413
}
14141414

14151415
// create new output
1416-
const createOutput = () => {
1417-
const { message, renderer, transfer: transferable } = this._createOutputCreationMessage(cellInfo, content, cellTop, offset, false, false);
1418-
this._sendMessageToWebview(message, transferable);
1419-
this.insetMapping.set(content.source, { outputId: message.outputId, versionId: content.source.model.versionId, cellInfo: cellInfo, renderer, cachedCreation: message });
1420-
this.hiddenInsetMapping.delete(content.source);
1421-
this.reversedInsetMapping.set(message.outputId, content.source);
1422-
};
1423-
1424-
createOutput();
1416+
const { message, renderer, transfer: transferable } = this._createOutputCreationMessage(cellInfo, content, cellTop, offset, false, false);
1417+
this._sendMessageToWebview(message, transferable);
1418+
this.insetMapping.set(content.source, { outputId: message.outputId, versionId: content.source.model.versionId, cellInfo: cellInfo, renderer, cachedCreation: message });
1419+
this.hiddenInsetMapping.delete(content.source);
1420+
this.reversedInsetMapping.set(message.outputId, content.source);
14251421
}
14261422

14271423
private createMetadata(output: ICellOutput, mimeType: string) {

src/vs/workbench/contrib/notebook/common/model/notebookCellOutputTextModel.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { Emitter } from 'vs/base/common/event';
77
import { Disposable } from 'vs/base/common/lifecycle';
8-
import { ICellOutput, IOutputDto, IOutputItemDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
8+
import { ICellOutput, IOutputDto, IOutputItemDto, compressOutputItemStreams, isTextStreamMime } from 'vs/workbench/contrib/notebook/common/notebookCommon';
99

1010
export class NotebookCellOutputTextModel extends Disposable implements ICellOutput {
1111

@@ -38,17 +38,46 @@ export class NotebookCellOutputTextModel extends Disposable implements ICellOutp
3838

3939
replaceData(rawData: IOutputDto) {
4040
this._rawOutput = rawData;
41+
this.optimizeOutputItems();
4142
this._versionId = this._versionId + 1;
42-
4343
this._onDidChangeData.fire();
4444
}
4545

4646
appendData(items: IOutputItemDto[]) {
4747
this._rawOutput.outputs.push(...items);
48+
this.optimizeOutputItems();
4849
this._versionId = this._versionId + 1;
4950
this._onDidChangeData.fire();
5051
}
5152

53+
private optimizeOutputItems() {
54+
if (this.outputs.length > 1 && this.outputs.every(item => isTextStreamMime(item.mime))) {
55+
// Look for the mimes in the items, and keep track of their order.
56+
// Merge the streams into one output item, per mime type.
57+
const mimeOutputs = new Map<string, Uint8Array[]>();
58+
const mimeTypes: string[] = [];
59+
this.outputs.forEach(item => {
60+
let items: Uint8Array[];
61+
if (mimeOutputs.has(item.mime)) {
62+
items = mimeOutputs.get(item.mime)!;
63+
} else {
64+
items = [];
65+
mimeOutputs.set(item.mime, items);
66+
mimeTypes.push(item.mime);
67+
}
68+
items.push(item.data.buffer);
69+
});
70+
this.outputs.length = 0;
71+
mimeTypes.forEach(mime => {
72+
const compressed = compressOutputItemStreams(mimeOutputs.get(mime)!);
73+
this.outputs.push({
74+
mime,
75+
data: compressed
76+
});
77+
});
78+
}
79+
}
80+
5281
toJSON(): IOutputDto {
5382
return {
5483
// data: this._data,
@@ -57,4 +86,6 @@ export class NotebookCellOutputTextModel extends Disposable implements ICellOutp
5786
outputId: this._rawOutput.outputId
5887
};
5988
}
89+
90+
6091
}

src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { TextModel } from 'vs/editor/common/model/textModel';
1616
import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';
1717
import { ILanguageService } from 'vs/editor/common/languages/language';
1818
import { NotebookCellOutputTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellOutputTextModel';
19-
import { CellInternalMetadataChangedEvent, CellKind, compressOutputItemStreams, ICell, ICellDto2, ICellOutput, IOutputDto, IOutputItemDto, isTextStreamMime, NotebookCellCollapseState, NotebookCellInternalMetadata, NotebookCellMetadata, NotebookCellOutputsSplice, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
19+
import { CellInternalMetadataChangedEvent, CellKind, ICell, ICellDto2, ICellOutput, IOutputDto, IOutputItemDto, NotebookCellCollapseState, NotebookCellInternalMetadata, NotebookCellMetadata, NotebookCellOutputsSplice, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
2020

2121
export class NotebookCellTextModel extends Disposable implements ICell {
2222
private readonly _onDidChangeOutputs = this._register(new Emitter<NotebookCellOutputsSplice>());
@@ -298,34 +298,6 @@ export class NotebookCellTextModel extends Disposable implements ICell {
298298
}
299299
}
300300

301-
private _optimizeOutputItems(output: ICellOutput) {
302-
if (output.outputs.length > 1 && output.outputs.every(item => isTextStreamMime(item.mime))) {
303-
// Look for the mimes in the items, and keep track of their order.
304-
// Merge the streams into one output item, per mime type.
305-
const mimeOutputs = new Map<string, Uint8Array[]>();
306-
const mimeTypes: string[] = [];
307-
output.outputs.forEach(item => {
308-
let items: Uint8Array[];
309-
if (mimeOutputs.has(item.mime)) {
310-
items = mimeOutputs.get(item.mime)!;
311-
} else {
312-
items = [];
313-
mimeOutputs.set(item.mime, items);
314-
mimeTypes.push(item.mime);
315-
}
316-
items.push(item.data.buffer);
317-
});
318-
output.outputs.length = 0;
319-
mimeTypes.forEach(mime => {
320-
const compressed = compressOutputItemStreams(mimeOutputs.get(mime)!);
321-
output.outputs.push({
322-
mime,
323-
data: compressed
324-
});
325-
});
326-
}
327-
}
328-
329301
replaceOutput(outputId: string, newOutputItem: ICellOutput) {
330302
const outputIndex = this.outputs.findIndex(output => output.outputId === outputId);
331303

@@ -335,7 +307,6 @@ export class NotebookCellTextModel extends Disposable implements ICell {
335307

336308
const output = this.outputs[outputIndex];
337309
output.replaceData(newOutputItem);
338-
this._optimizeOutputItems(output);
339310
this._onDidChangeOutputItems.fire();
340311
return true;
341312
}
@@ -353,8 +324,6 @@ export class NotebookCellTextModel extends Disposable implements ICell {
353324
} else {
354325
output.replaceData({ outputId: outputId, outputs: items, metadata: output.metadata });
355326
}
356-
357-
this._optimizeOutputItems(output);
358327
this._onDidChangeOutputItems.fire();
359328
return true;
360329
}

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,58 @@ suite('NotebookTextModel', () => {
311311
);
312312
});
313313

314+
test('appending streaming outputs', async function () {
315+
await withTestNotebook(
316+
[
317+
['var a = 1;', 'javascript', CellKind.Code, [], {}],
318+
],
319+
(editor) => {
320+
const textModel = editor.textModel;
321+
322+
textModel.applyEdits([
323+
{
324+
index: 0,
325+
editType: CellEditType.Output,
326+
append: true,
327+
outputs: [{
328+
outputId: 'append1',
329+
outputs: [{ mime: 'application/vnd.code.notebook.stdout', data: valueBytesFromString('append 1') }]
330+
}]
331+
}], true, undefined, () => undefined, undefined, true);
332+
const [output] = textModel.cells[0].outputs;
333+
assert.strictEqual(output.versionId, 0, 'initial output version is 0');
334+
335+
textModel.applyEdits([
336+
{
337+
editType: CellEditType.OutputItems,
338+
append: true,
339+
outputId: 'append1',
340+
items: [{
341+
mime: 'application/vnd.code.notebook.stdout', data: valueBytesFromString('append 2')
342+
}]
343+
}], true, undefined, () => undefined, undefined, true);
344+
assert.strictEqual(output.versionId, 1, 'version should bump per append');
345+
346+
textModel.applyEdits([
347+
{
348+
editType: CellEditType.OutputItems,
349+
append: true,
350+
outputId: 'append1',
351+
items: [{
352+
mime: 'application/vnd.code.notebook.stdout', data: valueBytesFromString('append 3')
353+
}]
354+
}], true, undefined, () => undefined, undefined, true);
355+
assert.strictEqual(output.versionId, 2, 'version should bump per append');
356+
357+
assert.strictEqual(textModel.cells.length, 1);
358+
assert.strictEqual(textModel.cells[0].outputs.length, 1, 'has 1 output');
359+
assert.strictEqual(output.outputId, 'append1');
360+
assert.strictEqual(output.outputs.length, 1, 'outputs are compressed');
361+
assert.strictEqual(output.outputs[0].data.toString(), 'append 1append 2append 3');
362+
}
363+
);
364+
});
365+
314366
test('metadata', async function () {
315367
await withTestNotebook(
316368
[

0 commit comments

Comments
 (0)