Path: blob/main/src/vs/workbench/contrib/notebook/common/model/notebookCellOutputTextModel.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { VSBuffer } from '../../../../../base/common/buffer.js';6import { Emitter } from '../../../../../base/common/event.js';7import { Disposable } from '../../../../../base/common/lifecycle.js';8import { ICellOutput, IOutputDto, IOutputItemDto, compressOutputItemStreams } from '../notebookCommon.js';9import { isTextStreamMime } from '../../../../../base/common/mime.js';1011export class NotebookCellOutputTextModel extends Disposable implements ICellOutput {1213private _onDidChangeData = this._register(new Emitter<void>());14onDidChangeData = this._onDidChangeData.event;1516get outputs() {17return this._rawOutput.outputs || [];18}1920get metadata(): Record<string, any> | undefined {21return this._rawOutput.metadata;22}2324get outputId(): string {25return this._rawOutput.outputId;26}2728/**29* Alternative output id that's reused when the output is updated.30*/31private _alternativeOutputId: string;3233get alternativeOutputId(): string {34return this._alternativeOutputId;35}3637private _versionId = 0;3839get versionId() {40return this._versionId;41}4243constructor(44private _rawOutput: IOutputDto45) {46super();4748this._alternativeOutputId = this._rawOutput.outputId;49}5051replaceData(rawData: IOutputDto) {52this.versionedBufferLengths = {};53this._rawOutput = rawData;54this.optimizeOutputItems();55this._versionId = this._versionId + 1;56this._onDidChangeData.fire();57}5859appendData(items: IOutputItemDto[]) {60this.trackBufferLengths();61this._rawOutput.outputs.push(...items);62this.optimizeOutputItems();63this._versionId = this._versionId + 1;64this._onDidChangeData.fire();65}6667private trackBufferLengths() {68this.outputs.forEach(output => {69if (isTextStreamMime(output.mime)) {70if (!this.versionedBufferLengths[output.mime]) {71this.versionedBufferLengths[output.mime] = {};72}73this.versionedBufferLengths[output.mime][this.versionId] = output.data.byteLength;74}75});76}7778// mime: versionId: buffer length79private versionedBufferLengths: Record<string, Record<number, number>> = {};8081appendedSinceVersion(versionId: number, mime: string): VSBuffer | undefined {82const bufferLength = this.versionedBufferLengths[mime]?.[versionId];83const output = this.outputs.find(output => output.mime === mime);84if (bufferLength && output) {85return output.data.slice(bufferLength);86}8788return undefined;89}9091private optimizeOutputItems() {92if (this.outputs.length > 1 && this.outputs.every(item => isTextStreamMime(item.mime))) {93// Look for the mimes in the items, and keep track of their order.94// Merge the streams into one output item, per mime type.95const mimeOutputs = new Map<string, Uint8Array[]>();96const mimeTypes: string[] = [];97this.outputs.forEach(item => {98let items: Uint8Array[];99if (mimeOutputs.has(item.mime)) {100items = mimeOutputs.get(item.mime)!;101} else {102items = [];103mimeOutputs.set(item.mime, items);104mimeTypes.push(item.mime);105}106items.push(item.data.buffer);107});108this.outputs.length = 0;109mimeTypes.forEach(mime => {110const compressionResult = compressOutputItemStreams(mimeOutputs.get(mime)!);111this.outputs.push({112mime,113data: compressionResult.data114});115if (compressionResult.didCompression) {116// we can't rely on knowing buffer lengths if we've erased previous lines117this.versionedBufferLengths = {};118}119});120}121}122123asDto(): IOutputDto {124return {125// data: this._data,126metadata: this._rawOutput.metadata,127outputs: this._rawOutput.outputs,128outputId: this._rawOutput.outputId129};130}131132bumpVersion() {133this._versionId = this._versionId + 1;134}135136}137138139