Skip to content

Commit 0edc352

Browse files
committed
test for ouput compression
1 parent 79c4954 commit 0edc352

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,15 @@ export class NotebookCellOutputTextModel extends Disposable implements ICellOutp
9696
});
9797
this.outputs.length = 0;
9898
mimeTypes.forEach(mime => {
99-
const compressed = compressOutputItemStreams(mimeOutputs.get(mime)!);
99+
const compressionResult = compressOutputItemStreams(mimeOutputs.get(mime)!);
100100
this.outputs.push({
101101
mime,
102-
data: compressed
102+
data: compressionResult.data
103103
});
104+
if (compressionResult.didCompression) {
105+
// we can't rely on knowing buffer lengths if we've erased previous lines
106+
this.versionedBufferLengths = {};
107+
}
104108
});
105109
}
106110
}

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,7 @@ const textDecoder = new TextDecoder();
996996
* Given a stream of individual stdout outputs, this function will return the compressed lines, escaping some of the common terminal escape codes.
997997
* E.g. some terminal escape codes would result in the previous line getting cleared, such if we had 3 lines and
998998
* last line contained such a code, then the result string would be just the first two lines.
999+
* @returns a single VSBuffer with the concatenated and compressed data, and whether any compression was done.
9991000
*/
10001001
export function compressOutputItemStreams(outputs: Uint8Array[]) {
10011002
const buffers: Uint8Array[] = [];
@@ -1008,13 +1009,17 @@ export function compressOutputItemStreams(outputs: Uint8Array[]) {
10081009
startAppending = true;
10091010
}
10101011
}
1011-
compressStreamBuffer(buffers);
1012-
return formatStreamText(VSBuffer.concat(buffers.map(buffer => VSBuffer.wrap(buffer))));
1012+
1013+
const didCompression = compressStreamBuffer(buffers);
1014+
const data = formatStreamText(VSBuffer.concat(buffers.map(buffer => VSBuffer.wrap(buffer))));
1015+
return { data, didCompression };
10131016
}
1014-
const MOVE_CURSOR_1_LINE_COMMAND = `${String.fromCharCode(27)}[A`;
1017+
1018+
export const MOVE_CURSOR_1_LINE_COMMAND = `${String.fromCharCode(27)}[A`;
10151019
const MOVE_CURSOR_1_LINE_COMMAND_BYTES = MOVE_CURSOR_1_LINE_COMMAND.split('').map(c => c.charCodeAt(0));
10161020
const LINE_FEED = 10;
10171021
function compressStreamBuffer(streams: Uint8Array[]) {
1022+
let didCompress = false;
10181023
streams.forEach((stream, index) => {
10191024
if (index === 0 || stream.length < MOVE_CURSOR_1_LINE_COMMAND.length) {
10201025
return;
@@ -1029,10 +1034,13 @@ function compressStreamBuffer(streams: Uint8Array[]) {
10291034
if (lastIndexOfLineFeed === -1) {
10301035
return;
10311036
}
1037+
1038+
didCompress = true;
10321039
streams[index - 1] = previousStream.subarray(0, lastIndexOfLineFeed);
10331040
streams[index] = stream.subarray(MOVE_CURSOR_1_LINE_COMMAND.length);
10341041
}
10351042
});
1043+
return didCompress;
10361044
}
10371045

10381046

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

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { ILanguageService } from 'vs/editor/common/languages/language';
1111
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
1212
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
1313
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
14-
import { CellEditType, CellKind, ICellEditOperation, NotebookTextModelChangedEvent, NotebookTextModelWillAddRemoveEvent, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
14+
import { CellEditType, CellKind, ICellEditOperation, MOVE_CURSOR_1_LINE_COMMAND, NotebookTextModelChangedEvent, NotebookTextModelWillAddRemoveEvent, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
1515
import { setupInstantiationService, TestCell, valueBytesFromString, withTestNotebook } from 'vs/workbench/contrib/notebook/test/browser/testNotebookEditor';
1616

1717
suite('NotebookTextModel', () => {
@@ -436,6 +436,48 @@ suite('NotebookTextModel', () => {
436436
);
437437
});
438438

439+
test('appending streaming outputs with compression', async function () {
440+
441+
await withTestNotebook(
442+
[
443+
['var a = 1;', 'javascript', CellKind.Code, [], {}],
444+
],
445+
(editor) => {
446+
const textModel = editor.textModel;
447+
448+
textModel.applyEdits([
449+
{
450+
index: 0,
451+
editType: CellEditType.Output,
452+
append: true,
453+
outputs: [{
454+
outputId: 'append1',
455+
outputs: [
456+
{ mime: stdOutMime, data: valueBytesFromString('append 1') },
457+
{ mime: stdOutMime, data: valueBytesFromString('\nappend 1') }]
458+
}]
459+
}], true, undefined, () => undefined, undefined, true);
460+
const [output] = textModel.cells[0].outputs;
461+
assert.strictEqual(output.versionId, 0, 'initial output version should be 0');
462+
463+
textModel.applyEdits([
464+
{
465+
editType: CellEditType.OutputItems,
466+
append: true,
467+
outputId: 'append1',
468+
items: [{
469+
mime: stdOutMime, data: valueBytesFromString(MOVE_CURSOR_1_LINE_COMMAND + '\nappend 2')
470+
}]
471+
}], true, undefined, () => undefined, undefined, true);
472+
assert.strictEqual(output.versionId, 1, 'version should bump per append');
473+
474+
assert.strictEqual(output.outputs[0].data.toString(), 'append 1\nappend 2');
475+
assert.strictEqual(output.appendedSinceVersion(0, stdOutMime), undefined,
476+
'compressing outputs should clear out previous versioned output buffers');
477+
}
478+
);
479+
});
480+
439481
test('appending multiple different mime streaming outputs', async function () {
440482
await withTestNotebook(
441483
[

0 commit comments

Comments
 (0)