mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-24 16:35:55 +01:00
* Transfer notebook output data as a VSBuffer This PR transfers notebook output as an VSBuffer instead of as a array of numbers. This significantly reduces the message size as well as the serialize/deserialize times To accomplish this, I've introduced a new `SerializableObjectWithBuffers` type. This specially marks rpc objects that contain VSBuffers. This is needed as our current RPC implementation can only efficently transfer VSBuffers that appears as top level arguments. The rpcProtocol now can also identify top level `SerializableObjectWithBuffers` arguments and ensure these are serialized more efficently. This is easier than trying to extract the `VSBuffer` proeprties to top level arguments. It also lets us easily support return types that may contain buffers * use SerializableObjectWithBuffers when dealing with (old) notebook controllers Co-authored-by: Johannes Rieken <johannes.rieken@gmail.com>
96 lines
2.1 KiB
TypeScript
96 lines
2.1 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { VSBuffer } from 'vs/base/common/buffer';
|
|
import { regExpFlags } from 'vs/base/common/strings';
|
|
import { URI, UriComponents } from 'vs/base/common/uri';
|
|
|
|
export function stringify(obj: any): string {
|
|
return JSON.stringify(obj, replacer);
|
|
}
|
|
|
|
export function parse(text: string): any {
|
|
let data = JSON.parse(text);
|
|
data = revive(data);
|
|
return data;
|
|
}
|
|
|
|
export const enum MarshalledId {
|
|
Uri = 1,
|
|
Regexp,
|
|
ScmResource,
|
|
ScmResourceGroup,
|
|
ScmProvider,
|
|
CommentController,
|
|
CommentThread,
|
|
CommentThreadReply,
|
|
CommentNode,
|
|
CommentThreadNode,
|
|
TimelineActionContext,
|
|
NotebookCellActionContext,
|
|
TestItemContext,
|
|
}
|
|
|
|
export interface MarshalledObject {
|
|
$mid: MarshalledId;
|
|
}
|
|
|
|
function replacer(key: string, value: any): any {
|
|
// URI is done via toJSON-member
|
|
if (value instanceof RegExp) {
|
|
return {
|
|
$mid: MarshalledId.Regexp,
|
|
source: value.source,
|
|
flags: regExpFlags(value),
|
|
};
|
|
}
|
|
return value;
|
|
}
|
|
|
|
|
|
type Deserialize<T> = T extends UriComponents ? URI
|
|
: T extends VSBuffer ? VSBuffer
|
|
: T extends object
|
|
? Revived<T>
|
|
: T;
|
|
|
|
export type Revived<T> = { [K in keyof T]: Deserialize<T[K]> };
|
|
|
|
export function revive<T = any>(obj: any, depth = 0): Revived<T> {
|
|
if (!obj || depth > 200) {
|
|
return obj;
|
|
}
|
|
|
|
if (typeof obj === 'object') {
|
|
|
|
switch ((<MarshalledObject>obj).$mid) {
|
|
case MarshalledId.Uri: return <any>URI.revive(obj);
|
|
case MarshalledId.Regexp: return <any>new RegExp(obj.source, obj.flags);
|
|
}
|
|
|
|
if (
|
|
obj instanceof VSBuffer
|
|
|| obj instanceof Uint8Array
|
|
) {
|
|
return <any>obj;
|
|
}
|
|
|
|
if (Array.isArray(obj)) {
|
|
for (let i = 0; i < obj.length; ++i) {
|
|
obj[i] = revive(obj[i], depth + 1);
|
|
}
|
|
} else {
|
|
// walk object
|
|
for (const key in obj) {
|
|
if (Object.hasOwnProperty.call(obj, key)) {
|
|
obj[key] = revive(obj[key], depth + 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
}
|