191
};
192
}
194
>
195
>
const enum EntryKind {
196
>
/** Initial complete object state, valid only as the first entry */
197
>
Initial = 0,
198
>
/** Property update */
199
>
Set = 1,
200
>
/** Array push/splice. */
201
>
Push = 2,
202
>
/** Delete a property */
203
>
Delete = 3,
204
>
}
205
>
206
>
type ObjectPath = (string | number)[];
207
>
208
>
type Entry =
209
>
| { kind: EntryKind.Initial; v: unknown }
210
>
/** Update a property of an object, replacing it entirely */
211
>
| { kind: EntryKind.Set; k: ObjectPath; v: unknown }
212
>
/** Delete a property of an object */
213
>
| { kind: EntryKind.Delete; k: ObjectPath }
214
>
/** Pushes 0 or more new entries to an array. If `i` is set, everything after that index is removed */
215
>
| { kind: EntryKind.Push; k: ObjectPath; v?: unknown[]; i?: number };
216
>
217
>
const LF = VSBuffer.fromString('\n');
218
>
219
>
/**
220
>
* Per-string cap (in UTF-16 code units, matching `string.length`) applied when
221
>
* {@link stringifyEntryWithFallback} retries after `JSON.stringify` throws
222
>
* `RangeError: Invalid string length` (V8's max string length is ~512 MiB on
223
>
* 64-bit). Any single string longer than this is replaced with a marker on
224
>
* retry. Generous so it triggers only on outliers.
225
>
*/
226
>
export const PERSIST_ENTRY_MAX_STRING_CHARS = 1 * 1024 * 1024;
227
>
228
>
/**
229
>
* Total-size budget (sum of `string.length` for tracked strings, in UTF-16
230
>
* code units) for the retry of {@link stringifyEntryWithFallback}. Once the
231
>
* cumulative tracked size during serialization exceeds this, remaining values
232
>
* are replaced with a marker.
233
>
*
234
>
* This is an approximation: JSON escaping, property keys, and non-string
235
>
* payload are not counted, so the actual output may be moderately larger.
236
>
* The cap is sized well under V8's max string length to leave ample headroom
237
>
* for that overhead.
238
>
*/
239
>
export const PERSIST_ENTRY_MAX_TOTAL_CHARS = 100 * 1024 * 1024;
240
>
241
>
const TRUNCATION_MARKER_PREFIX = '[VS Code: value truncated for persistence';
242
>
const TRUNCATION_MARKER_TOTAL = `${TRUNCATION_MARKER_PREFIX}; entry exceeded size budget]`;
243
>
244
>
/**
245
>
* Wraps `JSON.stringify(entry)` with a safety net for the V8 max-string-length
246
>
* limit. The common path is a single `JSON.stringify` with zero overhead. If
247
>
* stringification throws `RangeError` (the resulting JSON would exceed V8's
248
>
* ~512 MiB max string length — see microsoft/vscode#308843), retry with a
249
>
* replacer that truncates oversized strings. Extensions sometimes put very
250
>
* large content (browser dumps, command output, …) into chat result metadata;
251
>
* losing the tail of one such value is dramatically better than losing the
252
>
* entire chat session.
253
>
*/
254
>
export function stringifyEntryWithFallback(entry: unknown): string {
255
try {
256
return JSON.stringify(entry);