stream-monaco 0.0.41 → 0.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -522,6 +522,14 @@ function createScrollWatcherForEditor(ed, opts) {
522
522
  return api;
523
523
  }
524
524
 
525
+ //#endregion
526
+ //#region src/utils/textChunks.ts
527
+ function countLineBreaks(text) {
528
+ let count = 0;
529
+ for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) === 10) count += 1;
530
+ return count;
531
+ }
532
+
525
533
  //#endregion
526
534
  //#region src/core/diffAppearance.ts
527
535
  function parseCssColorRgb(color) {
@@ -4111,6 +4119,8 @@ var DiffEditorManager = class DiffEditorManager {
4111
4119
  this.createDomDisposable(this.diffHunkDisposables, this.diffHunkUpperNode, "mouseleave", () => this.scheduleHideDiffHunkActions());
4112
4120
  this.createDomDisposable(this.diffHunkDisposables, this.diffHunkLowerNode, "mouseenter", () => this.cancelScheduledHideDiffHunkActions());
4113
4121
  this.createDomDisposable(this.diffHunkDisposables, this.diffHunkLowerNode, "mouseleave", () => this.scheduleHideDiffHunkActions());
4122
+ this.createDomDisposable(this.diffHunkDisposables, this.diffHunkUpperNode, "wheel", (event) => this.handleDiffHunkWheel(event, "upper"));
4123
+ this.createDomDisposable(this.diffHunkDisposables, this.diffHunkLowerNode, "wheel", (event) => this.handleDiffHunkWheel(event, "lower"));
4114
4124
  overlay.append(this.diffHunkUpperNode, this.diffHunkLowerNode);
4115
4125
  const originalEditor = this.diffEditorView.getOriginalEditor();
4116
4126
  const modifiedEditor = this.diffEditorView.getModifiedEditor();
@@ -4134,6 +4144,17 @@ var DiffEditorManager = class DiffEditorManager {
4134
4144
  }));
4135
4145
  this.diffHunkLineChanges = this.getEffectiveLineChanges();
4136
4146
  }
4147
+ handleDiffHunkWheel(event, side) {
4148
+ var _editor$setScrollLeft, _editor$getScrollLeft, _editor$setScrollTop, _editor$getScrollTop2;
4149
+ if (Math.abs(event.deltaX) < .5 && Math.abs(event.deltaY) < .5) return;
4150
+ if (!this.diffEditorView) return;
4151
+ const editor = this.isDiffInlineMode() || side === "lower" ? this.diffEditorView.getModifiedEditor() : this.diffEditorView.getOriginalEditor();
4152
+ event.preventDefault();
4153
+ event.stopPropagation();
4154
+ (_editor$setScrollLeft = editor.setScrollLeft) === null || _editor$setScrollLeft === void 0 || _editor$setScrollLeft.call(editor, (((_editor$getScrollLeft = editor.getScrollLeft) === null || _editor$getScrollLeft === void 0 ? void 0 : _editor$getScrollLeft.call(editor)) ?? 0) + event.deltaX);
4155
+ (_editor$setScrollTop = editor.setScrollTop) === null || _editor$setScrollTop === void 0 || _editor$setScrollTop.call(editor, (((_editor$getScrollTop2 = editor.getScrollTop) === null || _editor$getScrollTop2 === void 0 ? void 0 : _editor$getScrollTop2.call(editor)) ?? 0) + event.deltaY);
4156
+ this.hideDiffHunkActions();
4157
+ }
4137
4158
  cancelScheduledHideDiffHunkActions() {
4138
4159
  if (this.diffHunkHideTimer != null) {
4139
4160
  clearTimeout(this.diffHunkHideTimer);
@@ -4413,9 +4434,10 @@ var DiffEditorManager = class DiffEditorManager {
4413
4434
  shouldAutoScrollDiff: this.shouldAutoScrollDiff
4414
4435
  });
4415
4436
  if (!this.diffEditorView) return;
4437
+ if (!(this.diffAutoScroll && this.autoScrollOnUpdate && this.shouldAutoScrollDiff)) return;
4416
4438
  const hasV = this.hasVerticalScrollbarModified();
4417
4439
  log("diff", "hasVerticalScrollbarModified ->", hasV);
4418
- if (!(this.diffAutoScroll && this.autoScrollOnUpdate && this.shouldAutoScrollDiff && hasV)) return;
4440
+ if (!hasV) return;
4419
4441
  const me = this.diffEditorView.getModifiedEditor();
4420
4442
  const model = me.getModel();
4421
4443
  const currentLine = (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
@@ -4637,7 +4659,7 @@ var DiffEditorManager = class DiffEditorManager {
4637
4659
  this.diffComputedVersions = null;
4638
4660
  this.diffPresentationDisposables.push(this.diffEditorView.onDidUpdateDiff(() => {
4639
4661
  this.diffComputedVersions = this.captureCurrentDiffVersions();
4640
- this.syncDiffEditorLayoutToContainer();
4662
+ this.scheduleSyncDiffEditorLayoutToContainer();
4641
4663
  this.scheduleSyncDiffPresentationDecorations();
4642
4664
  }));
4643
4665
  this.diffPresentationDisposables.push(oEditor.onDidChangeModelContent(() => {
@@ -4802,6 +4824,7 @@ var DiffEditorManager = class DiffEditorManager {
4802
4824
  }
4803
4825
  updateModified(newCode, codeLanguage) {
4804
4826
  if (!this.diffEditorView || !this.modifiedModel) return;
4827
+ this.syncLastKnownModified();
4805
4828
  if (codeLanguage) {
4806
4829
  const lang = processedLanguage(codeLanguage);
4807
4830
  if (lang && this.modifiedModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.modifiedModel, lang);
@@ -4814,7 +4837,7 @@ var DiffEditorManager = class DiffEditorManager {
4814
4837
  if (tailAppend) this.appendModified(newCode.slice(prev.length), codeLanguage);
4815
4838
  else {
4816
4839
  this.flushModifiedAppendBufferSync();
4817
- const prevAfterFlush = this.modifiedModel.getValue();
4840
+ const prevAfterFlush = this.lastKnownModifiedCode ?? this.modifiedModel.getValue();
4818
4841
  const prevLine = this.modifiedModel.getLineCount();
4819
4842
  this.applyMinimalEditToModel(this.modifiedModel, prevAfterFlush, newCode);
4820
4843
  const newLine = this.modifiedModel.getLineCount();
@@ -5064,6 +5087,7 @@ var DiffEditorManager = class DiffEditorManager {
5064
5087
  }
5065
5088
  const { original, modified, lang } = this.pendingDiffUpdate;
5066
5089
  this.pendingDiffUpdate = null;
5090
+ this.syncLastKnownModified();
5067
5091
  this.flushOriginalAppendBufferSync();
5068
5092
  this.flushModifiedAppendBufferSync();
5069
5093
  if (lang) {
@@ -5084,7 +5108,7 @@ var DiffEditorManager = class DiffEditorManager {
5084
5108
  else this.applyMinimalEditToModel(o, prevO, original);
5085
5109
  this.lastKnownOriginalCode = original;
5086
5110
  }
5087
- const prevM = m.getValue();
5111
+ const prevM = this.lastKnownModifiedCode;
5088
5112
  const prevMLineCount = m.getLineCount();
5089
5113
  const modifiedTailAppend = prevM !== modified && modified.startsWith(prevM) && prevM.length < modified.length;
5090
5114
  const hasContentChange = prevO !== original || prevM !== modified;
@@ -5125,6 +5149,33 @@ var DiffEditorManager = class DiffEditorManager {
5125
5149
  this.preserveNativeDiffDecorationsOnStaleAppend = true;
5126
5150
  this.appendToModel(this.modifiedModel, text);
5127
5151
  }
5152
+ splitAppendTextForProgressiveFlush(text, maxChunkChars = 12e3, maxChunkLines = 200) {
5153
+ if (!text || text.length <= maxChunkChars) return [text];
5154
+ const chunks = [];
5155
+ let start = 0;
5156
+ let lineCount = 0;
5157
+ let lastSafeEnd = 0;
5158
+ for (let i = 0; i < text.length; i++) {
5159
+ if (text.charCodeAt(i) === 10) {
5160
+ lineCount += 1;
5161
+ lastSafeEnd = i + 1;
5162
+ }
5163
+ if (i - start + 1 < maxChunkChars && lineCount < maxChunkLines) continue;
5164
+ let end = lastSafeEnd > start ? lastSafeEnd : i + 1;
5165
+ if (end < text.length) {
5166
+ const prev = text.charCodeAt(end - 1);
5167
+ const next = text.charCodeAt(end);
5168
+ if (prev >= 55296 && prev <= 56319 && next >= 56320 && next <= 57343) end += 1;
5169
+ }
5170
+ chunks.push(text.slice(start, end));
5171
+ start = end;
5172
+ i = end - 1;
5173
+ lineCount = 0;
5174
+ lastSafeEnd = start;
5175
+ }
5176
+ if (start < text.length) chunks.push(text.slice(start));
5177
+ return chunks.length ? chunks : [text];
5178
+ }
5128
5179
  async flushAppendBufferDiff() {
5129
5180
  if (!this.diffEditorView) return;
5130
5181
  if (this.appendBufferOriginalDiff.length === 0 && this.appendBufferModifiedDiff.length === 0) return;
@@ -5145,17 +5196,16 @@ var DiffEditorManager = class DiffEditorManager {
5145
5196
  return;
5146
5197
  }
5147
5198
  let parts = this.appendBufferModifiedDiff.splice(0);
5199
+ if (parts.length === 0) {
5200
+ this.eagerlyGrowDiffContainerHeight();
5201
+ return;
5202
+ }
5148
5203
  const prevLineInit = model.getLineCount();
5149
5204
  const totalText = parts.join("");
5150
5205
  const totalChars = totalText.length;
5151
- if (parts.length === 1 && totalChars > 5e3) {
5152
- const lines = totalText.split(/\r?\n/);
5153
- const chunkSize = 200;
5154
- const chunks = [];
5155
- for (let i = 0; i < lines.length; i += chunkSize) chunks.push(`${lines.slice(i, i + chunkSize).join("\n")}\n`);
5156
- if (chunks.length > 1) parts = chunks;
5157
- }
5158
- const applyChunked = parts.length > 1 && (totalChars > 2e3 || model.getLineCount && model.getLineCount() + 0 - prevLineInit > 50);
5206
+ const totalLineBreaks = countLineBreaks(totalText);
5207
+ if (parts.length === 1 && totalChars > 5e3) parts = this.splitAppendTextForProgressiveFlush(totalText);
5208
+ const applyChunked = parts.length > 1 && (totalChars > 2e3 || totalLineBreaks > 50);
5159
5209
  log("diff", "flushAppendBufferDiff start", {
5160
5210
  partsCount: parts.length,
5161
5211
  totalChars,
@@ -5174,6 +5224,8 @@ var DiffEditorManager = class DiffEditorManager {
5174
5224
  } catch {}
5175
5225
  if (applyChunked) {
5176
5226
  log("diff", "flushAppendBufferDiff applying chunked", { partsLen: parts.length });
5227
+ if (this.lastKnownModifiedCode == null) this.lastKnownModifiedCode = model.getValue();
5228
+ let currentLength = this.lastKnownModifiedCode.length;
5177
5229
  let idx = 0;
5178
5230
  for (const part of parts) {
5179
5231
  if (!part) continue;
@@ -5183,17 +5235,9 @@ var DiffEditorManager = class DiffEditorManager {
5183
5235
  partLen: part.length,
5184
5236
  prevLine
5185
5237
  });
5186
- const lastColumn$1 = model.getLineMaxColumn(prevLine);
5187
- const range$1 = new monaco_shim_exports.Range(prevLine, lastColumn$1, prevLine, lastColumn$1);
5188
5238
  this.preserveNativeDiffDecorationsOnStaleAppend = true;
5189
- this.runAsProgrammaticModifiedContentChange(() => {
5190
- model.applyEdits([{
5191
- range: range$1,
5192
- text: part,
5193
- forceMoveMarkers: true
5194
- }]);
5195
- });
5196
- this.lastKnownModifiedCode = model.getValue();
5239
+ this.appendToModel(model, part, currentLength);
5240
+ currentLength += part.length;
5197
5241
  const newLine$1 = model.getLineCount();
5198
5242
  this.lastKnownModifiedLineCount = newLine$1;
5199
5243
  await new Promise((resolve) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(resolve) : setTimeout(resolve, 0));
@@ -5219,23 +5263,15 @@ var DiffEditorManager = class DiffEditorManager {
5219
5263
  newLine: newLine$1
5220
5264
  });
5221
5265
  }
5266
+ this.lastKnownModifiedCode = model.getValue();
5222
5267
  if (suppressedByFlush) watcherApi.setSuppressed(false);
5223
5268
  return;
5224
5269
  }
5225
5270
  const text = totalText;
5226
5271
  this.appendBufferModifiedDiff.length = 0;
5227
5272
  prevLine = model.getLineCount();
5228
- const lastColumn = model.getLineMaxColumn(prevLine);
5229
- const range = new monaco_shim_exports.Range(prevLine, lastColumn, prevLine, lastColumn);
5230
5273
  this.preserveNativeDiffDecorationsOnStaleAppend = true;
5231
- this.runAsProgrammaticModifiedContentChange(() => {
5232
- model.applyEdits([{
5233
- range,
5234
- text,
5235
- forceMoveMarkers: true
5236
- }]);
5237
- });
5238
- this.lastKnownModifiedCode = model.getValue();
5274
+ this.appendToModel(model, text);
5239
5275
  const newLine = model.getLineCount();
5240
5276
  this.lastKnownModifiedLineCount = newLine;
5241
5277
  this.eagerlyGrowDiffContainerHeight();
@@ -5278,8 +5314,30 @@ var DiffEditorManager = class DiffEditorManager {
5278
5314
  });
5279
5315
  if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
5280
5316
  }
5281
- appendToModel(model, appendText) {
5317
+ getModelValueLength(model) {
5318
+ const getValueLength = model.getValueLength;
5319
+ if (typeof getValueLength === "function") try {
5320
+ return getValueLength.call(model);
5321
+ } catch {}
5322
+ return model.getValue().length;
5323
+ }
5324
+ mergeKnownAppend(known, appendText, previousLength, model) {
5325
+ if (known == null) return model.getValue();
5326
+ const nextLength = previousLength + appendText.length;
5327
+ if (known.length === previousLength) return known + appendText;
5328
+ if (known.length >= nextLength && known.slice(previousLength, nextLength) === appendText) return known;
5329
+ return model.getValue();
5330
+ }
5331
+ syncKnownCodeAfterAppend(model, appendText, previousLength) {
5332
+ if (model === this.originalModel) {
5333
+ this.lastKnownOriginalCode = this.mergeKnownAppend(this.lastKnownOriginalCode, appendText, previousLength, model);
5334
+ return;
5335
+ }
5336
+ if (model === this.modifiedModel) this.lastKnownModifiedCode = this.mergeKnownAppend(this.lastKnownModifiedCode, appendText, previousLength, model);
5337
+ }
5338
+ appendToModel(model, appendText, knownLength) {
5282
5339
  if (!appendText) return;
5340
+ const previousLength = knownLength != null ? knownLength : this.getModelValueLength(model);
5283
5341
  const lastLine = model.getLineCount();
5284
5342
  const lastColumn = model.getLineMaxColumn(lastLine);
5285
5343
  const range = new monaco_shim_exports.Range(lastLine, lastColumn, lastLine, lastColumn);
@@ -5291,6 +5349,7 @@ var DiffEditorManager = class DiffEditorManager {
5291
5349
  }]);
5292
5350
  });
5293
5351
  if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
5352
+ this.syncKnownCodeAfterAppend(model, appendText, previousLength);
5294
5353
  }
5295
5354
  applyModelEdit(model, fn) {
5296
5355
  if (model === this.modifiedModel) {
@@ -5328,6 +5387,8 @@ var EditorManager = class {
5328
5387
  minimalEditMaxChangeRatioValue = minimalEditMaxChangeRatio;
5329
5388
  lastUpdateFlushTime = 0;
5330
5389
  updateThrottleTimer = null;
5390
+ lastAppendFlushTime = 0;
5391
+ appendFlushThrottleTimer = null;
5331
5392
  shouldAutoScroll = true;
5332
5393
  scrollWatcher = null;
5333
5394
  scrollWatcherSuppressionTimer = null;
@@ -5427,6 +5488,10 @@ var EditorManager = class {
5427
5488
  clearTimeout(this.updateThrottleTimer);
5428
5489
  this.updateThrottleTimer = null;
5429
5490
  }
5491
+ if (this.appendFlushThrottleTimer != null) {
5492
+ clearTimeout(this.appendFlushThrottleTimer);
5493
+ this.appendFlushThrottleTimer = null;
5494
+ }
5430
5495
  }
5431
5496
  initDebugFlag() {
5432
5497
  if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) {
@@ -5523,6 +5588,14 @@ var EditorManager = class {
5523
5588
  }
5524
5589
  maybeScrollToBottom(targetLine) {
5525
5590
  this.rafScheduler.schedule("maybe-scroll", () => {
5591
+ if (!(this.autoScrollOnUpdate && this.shouldAutoScroll)) {
5592
+ this.dlog("maybeScrollToBottom skipped (auto-scroll disabled)", {
5593
+ autoScrollOnUpdate: this.autoScrollOnUpdate,
5594
+ shouldAutoScroll: this.shouldAutoScroll,
5595
+ targetLine
5596
+ });
5597
+ return;
5598
+ }
5526
5599
  const hasVS = this.hasVerticalScrollbar();
5527
5600
  this.dlog("maybeScrollToBottom called", {
5528
5601
  autoScrollOnUpdate: this.autoScrollOnUpdate,
@@ -5530,8 +5603,8 @@ var EditorManager = class {
5530
5603
  hasVerticalScrollbar: hasVS,
5531
5604
  targetLine
5532
5605
  });
5533
- if (!(this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar())) {
5534
- this.dlog("maybeScrollToBottom skipped (auto-scroll conditions not met)");
5606
+ if (!hasVS) {
5607
+ this.dlog("maybeScrollToBottom skipped (no vertical scrollbar)");
5535
5608
  return;
5536
5609
  }
5537
5610
  const model = this.editorView.getModel();
@@ -5791,7 +5864,7 @@ var EditorManager = class {
5791
5864
  this.lastScrollTop = v;
5792
5865
  }
5793
5866
  });
5794
- this.maybeScrollToBottom();
5867
+ if (this.shouldAutoScroll) this.maybeScrollToBottom();
5795
5868
  return this.editorView;
5796
5869
  }
5797
5870
  syncLastKnownCode() {
@@ -5962,10 +6035,31 @@ var EditorManager = class {
5962
6035
  this.appendBuffer.push(appendText);
5963
6036
  if (!this.appendBufferScheduled) {
5964
6037
  this.appendBufferScheduled = true;
5965
- this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
6038
+ this.scheduleFlushAppendBuffer();
5966
6039
  }
5967
6040
  }
5968
6041
  }
6042
+ scheduleFlushAppendBuffer() {
6043
+ const schedule = () => {
6044
+ this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
6045
+ };
6046
+ if (!this.updateThrottleMs) {
6047
+ schedule();
6048
+ return;
6049
+ }
6050
+ const now = Date.now();
6051
+ const since = now - this.lastAppendFlushTime;
6052
+ if (since >= this.updateThrottleMs) {
6053
+ schedule();
6054
+ return;
6055
+ }
6056
+ if (this.appendFlushThrottleTimer != null) return;
6057
+ const wait = this.updateThrottleMs - since;
6058
+ this.appendFlushThrottleTimer = setTimeout(() => {
6059
+ this.appendFlushThrottleTimer = null;
6060
+ schedule();
6061
+ }, wait);
6062
+ }
5969
6063
  applyMinimalEdit(prev, next) {
5970
6064
  if (!this.editorView) return;
5971
6065
  const model = this.editorView.getModel();
@@ -6006,6 +6100,7 @@ var EditorManager = class {
6006
6100
  if (!this.editorView) return;
6007
6101
  if (this.appendBuffer.length === 0) return;
6008
6102
  this.appendBufferScheduled = false;
6103
+ this.lastAppendFlushTime = Date.now();
6009
6104
  const model = this.editorView.getModel();
6010
6105
  if (!model) {
6011
6106
  this.appendBuffer.length = 0;
@@ -6060,6 +6155,11 @@ var EditorManager = class {
6060
6155
  this.updateThrottleTimer = null;
6061
6156
  this.rafScheduler.schedule("update", () => this.flushPendingUpdate());
6062
6157
  }
6158
+ if (!this.updateThrottleMs && this.appendFlushThrottleTimer != null) {
6159
+ clearTimeout(this.appendFlushThrottleTimer);
6160
+ this.appendFlushThrottleTimer = null;
6161
+ this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
6162
+ }
6063
6163
  }
6064
6164
  getUpdateThrottleMs() {
6065
6165
  return this.updateThrottleMs;
@@ -6136,6 +6236,8 @@ function arraysEqual(a, b) {
6136
6236
  const LEGACY_ONIG_INIT_KEY = "__streamMonacoLegacyOnigurumaInit__";
6137
6237
  const LEGACY_ENGINE_KEY = "__streamMonacoLegacyShikiEngine__";
6138
6238
  const LEGACY_MONACO_LANGS_INIT_KEY = "__streamMonacoLegacyMonacoLangsInit__";
6239
+ const PERF_HOOKS_ENABLED_KEY = "__STREAM_MONACO_ENABLE_INTERNAL_PERF_HOOKS__";
6240
+ let instrumentedHighlighterCache = /* @__PURE__ */ new WeakMap();
6139
6241
  async function awaitLegacyOnigurumaInitIfPresent() {
6140
6242
  try {
6141
6243
  var _globalThis;
@@ -6186,9 +6288,109 @@ let lastPatchedHighlighter = null;
6186
6288
  let lastPatchedLanguages = /* @__PURE__ */ new Set();
6187
6289
  const monacoThemeByKey = /* @__PURE__ */ new Map();
6188
6290
  const monacoLanguageSet = /* @__PURE__ */ new Set();
6291
+ function nowMs() {
6292
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
6293
+ }
6294
+ function isPerfHooksEnabled() {
6295
+ try {
6296
+ var _globalThis4;
6297
+ return typeof globalThis !== "undefined" && ((_globalThis4 = globalThis) === null || _globalThis4 === void 0 ? void 0 : _globalThis4[PERF_HOOKS_ENABLED_KEY]) === true;
6298
+ } catch {
6299
+ return false;
6300
+ }
6301
+ }
6302
+ function getPerfHook(name) {
6303
+ if (!isPerfHooksEnabled()) return null;
6304
+ try {
6305
+ var _STREAM_MONACO_PERF__;
6306
+ if (typeof globalThis === "undefined") return null;
6307
+ const hook = (_STREAM_MONACO_PERF__ = globalThis.__STREAM_MONACO_PERF__) === null || _STREAM_MONACO_PERF__ === void 0 ? void 0 : _STREAM_MONACO_PERF__[name];
6308
+ return typeof hook === "function" ? hook : null;
6309
+ } catch {
6310
+ return null;
6311
+ }
6312
+ }
6313
+ function getTokenizationPerfHook() {
6314
+ return getPerfHook("recordTokenize");
6315
+ }
6316
+ function getGrammarTokenizationPerfHook() {
6317
+ return getPerfHook("recordGrammarTokenize");
6318
+ }
6319
+ function getThemeRegistrationPerfHook() {
6320
+ return getPerfHook("recordThemeRegistration");
6321
+ }
6322
+ function recordTokenize(hook, language, durationMs, line, tokenCount, failed) {
6323
+ if (!hook) return;
6324
+ try {
6325
+ hook({
6326
+ language,
6327
+ durationMs,
6328
+ lineLength: line.length,
6329
+ lineSample: line.slice(0, 120),
6330
+ tokenCount,
6331
+ failed
6332
+ });
6333
+ } catch {}
6334
+ }
6335
+ function recordGrammarTokenize(language, durationMs, line, stoppedEarly, tokenCount) {
6336
+ const hook = getGrammarTokenizationPerfHook();
6337
+ if (!hook) return;
6338
+ try {
6339
+ hook({
6340
+ language,
6341
+ durationMs,
6342
+ lineLength: line.length,
6343
+ lineSample: line.slice(0, 120),
6344
+ stoppedEarly,
6345
+ tokenCount
6346
+ });
6347
+ } catch {}
6348
+ }
6349
+ function recordThemeRegistration(event) {
6350
+ const hook = getThemeRegistrationPerfHook();
6351
+ if (!hook) return;
6352
+ try {
6353
+ hook(event);
6354
+ } catch {}
6355
+ }
6356
+ function getProxyMember(target, prop) {
6357
+ const value = Reflect.get(target, prop, target);
6358
+ return typeof value === "function" ? value.bind(target) : value;
6359
+ }
6189
6360
  function themeKey(t) {
6190
6361
  return typeof t === "string" ? t : t.name ?? JSON.stringify(t);
6191
6362
  }
6363
+ function maybeInstrumentHighlighterGrammar(highlighter) {
6364
+ if (!getGrammarTokenizationPerfHook()) return highlighter;
6365
+ if (!highlighter || typeof highlighter !== "object" && typeof highlighter !== "function") return highlighter;
6366
+ const cached = instrumentedHighlighterCache.get(highlighter);
6367
+ if (cached) return cached;
6368
+ const grammarProxyCache = /* @__PURE__ */ new WeakMap();
6369
+ const instrumentedHighlighter = new Proxy(highlighter, { get(target, prop, _receiver) {
6370
+ if (prop !== "getLanguage") return getProxyMember(target, prop);
6371
+ return (language) => {
6372
+ const grammar = target.getLanguage(language);
6373
+ if (!grammar || typeof grammar !== "object" || typeof grammar.tokenizeLine2 !== "function") return grammar;
6374
+ const cachedGrammar = grammarProxyCache.get(grammar);
6375
+ if (cachedGrammar) return cachedGrammar;
6376
+ const instrumentedGrammar = new Proxy(grammar, { get(grammarTarget, grammarProp, _grammarReceiver) {
6377
+ if (grammarProp !== "tokenizeLine2") return getProxyMember(grammarTarget, grammarProp);
6378
+ const originalTokenizeLine2 = grammarTarget.tokenizeLine2.bind(grammarTarget);
6379
+ return (line, ruleStack, timeLimit) => {
6380
+ var _result$tokens;
6381
+ const startedAt = nowMs();
6382
+ const result = originalTokenizeLine2(line, ruleStack, timeLimit);
6383
+ recordGrammarTokenize(language, nowMs() - startedAt, line, !!(result === null || result === void 0 ? void 0 : result.stoppedEarly), typeof (result === null || result === void 0 || (_result$tokens = result.tokens) === null || _result$tokens === void 0 ? void 0 : _result$tokens.length) === "number" ? result.tokens.length / 2 : 0);
6384
+ return result;
6385
+ };
6386
+ } });
6387
+ grammarProxyCache.set(grammar, instrumentedGrammar);
6388
+ return instrumentedGrammar;
6389
+ };
6390
+ } });
6391
+ instrumentedHighlighterCache.set(highlighter, instrumentedHighlighter);
6392
+ return instrumentedHighlighter;
6393
+ }
6192
6394
  async function ensureMonacoHighlighter(themes, languages$1) {
6193
6395
  for (const t of themes) monacoThemeByKey.set(themeKey(t), t);
6194
6396
  for (const l of languages$1) monacoLanguageSet.add(l);
@@ -6198,7 +6400,11 @@ async function ensureMonacoHighlighter(themes, languages$1) {
6198
6400
  monacoHighlighterPromise = createHighlighterWithLegacyEngineIfNeeded({
6199
6401
  themes: initialThemes,
6200
6402
  langs: initialLangs
6201
- }).then((h$1) => h$1);
6403
+ }).then((h$1) => {
6404
+ h$1.__streamMonacoLoadedThemes = new Set(initialThemes.map((t) => themeKey(t)));
6405
+ h$1.__streamMonacoLoadedLangs = new Set(initialLangs);
6406
+ return h$1;
6407
+ });
6202
6408
  }
6203
6409
  const h = await monacoHighlighterPromise;
6204
6410
  const wantsThemes = Array.from(monacoThemeByKey.values());
@@ -6226,7 +6432,11 @@ async function ensureMonacoHighlighter(themes, languages$1) {
6226
6432
  const p = createHighlighterWithLegacyEngineIfNeeded({
6227
6433
  themes: wantsThemes,
6228
6434
  langs: wantsLangs
6229
- }).then((hh) => hh);
6435
+ }).then((hh) => {
6436
+ hh.__streamMonacoLoadedThemes = new Set(wantsThemes.map((t) => themeKey(t)));
6437
+ hh.__streamMonacoLoadedLangs = new Set(wantsLangs);
6438
+ return hh;
6439
+ });
6230
6440
  monacoHighlighterPromise = p;
6231
6441
  return p;
6232
6442
  }
@@ -6245,6 +6455,7 @@ function clearHighlighterCache() {
6245
6455
  monacoThemeByKey.clear();
6246
6456
  monacoLanguageSet.clear();
6247
6457
  themeRegisterPromise = null;
6458
+ instrumentedHighlighterCache = /* @__PURE__ */ new WeakMap();
6248
6459
  languagesRegistered = false;
6249
6460
  currentLanguages = [];
6250
6461
  }
@@ -6311,9 +6522,15 @@ async function getOrCreateHighlighter(themes, languages$1) {
6311
6522
  */
6312
6523
  async function registerMonacoThemes(themes, languages$1) {
6313
6524
  return enqueueRegistration(async () => {
6525
+ const registrationStartedAt = nowMs();
6526
+ let ensureHighlighterMs = 0;
6527
+ let patchMonacoMs = 0;
6528
+ let patchedMonaco = false;
6314
6529
  registerMonacoLanguages(languages$1);
6315
6530
  const p = (async () => {
6531
+ const ensureHighlighterStartedAt = nowMs();
6316
6532
  const highlighter = await ensureMonacoHighlighter(themes, languages$1);
6533
+ ensureHighlighterMs = nowMs() - ensureHighlighterStartedAt;
6317
6534
  const wantsLangs = Array.from(monacoLanguageSet.values());
6318
6535
  const needsLanguagePatch = lastPatchedHighlighter !== highlighter || wantsLangs.some((l) => !lastPatchedLanguages.has(l));
6319
6536
  if (needsLanguagePatch) {
@@ -6334,9 +6551,17 @@ async function registerMonacoThemes(themes, languages$1) {
6334
6551
  provider = {
6335
6552
  ...provider,
6336
6553
  tokenize(line, state) {
6554
+ const hook = getTokenizationPerfHook();
6555
+ const startedAt = hook ? nowMs() : 0;
6556
+ let tokenCount = 0;
6557
+ let failed = false;
6337
6558
  try {
6338
- return originalTokenize(line, state);
6559
+ const result = originalTokenize(line, state);
6560
+ tokenCount = Array.isArray(result === null || result === void 0 ? void 0 : result.tokens) ? result.tokens.length : 0;
6561
+ return result;
6339
6562
  } catch {
6563
+ failed = true;
6564
+ tokenCount = 1;
6340
6565
  return {
6341
6566
  endState: state,
6342
6567
  tokens: [{
@@ -6344,6 +6569,8 @@ async function registerMonacoThemes(themes, languages$1) {
6344
6569
  scopes: ""
6345
6570
  }]
6346
6571
  };
6572
+ } finally {
6573
+ if (hook) recordTokenize(hook, lang, nowMs() - startedAt, line, tokenCount, failed);
6347
6574
  }
6348
6575
  }
6349
6576
  };
@@ -6352,7 +6579,10 @@ async function registerMonacoThemes(themes, languages$1) {
6352
6579
  }
6353
6580
  }
6354
6581
  };
6355
- shikiToMonaco(highlighter, monacoProxy);
6582
+ const patchMonacoStartedAt = nowMs();
6583
+ shikiToMonaco(maybeInstrumentHighlighterGrammar(highlighter), monacoProxy);
6584
+ patchMonacoMs = nowMs() - patchMonacoStartedAt;
6585
+ patchedMonaco = true;
6356
6586
  lastPatchedHighlighter = highlighter;
6357
6587
  lastPatchedLanguages = new Set(wantsLangs);
6358
6588
  }
@@ -6362,6 +6592,14 @@ async function registerMonacoThemes(themes, languages$1) {
6362
6592
  setThemeRegisterPromise(p);
6363
6593
  try {
6364
6594
  const res = await p;
6595
+ recordThemeRegistration({
6596
+ durationMs: nowMs() - registrationStartedAt,
6597
+ ensureHighlighterMs,
6598
+ patchMonacoMs,
6599
+ themes: themes.length,
6600
+ languages: languages$1.length,
6601
+ patchedMonaco
6602
+ });
6365
6603
  return res;
6366
6604
  } catch (e) {
6367
6605
  setThemeRegisterPromise(null);
@@ -6495,7 +6733,8 @@ function useMonaco(monacoOptions = {}) {
6495
6733
  let modifiedModel = null;
6496
6734
  const themes = monacoOptions.themes && ((_monacoOptions$themes = monacoOptions.themes) === null || _monacoOptions$themes === void 0 ? void 0 : _monacoOptions$themes.length) ? monacoOptions.themes : defaultThemes;
6497
6735
  if (!Array.isArray(themes) || themes.length < 2) throw new Error("Monaco themes must be an array with at least two themes: [darkTheme, lightTheme]");
6498
- const languages$1 = monacoOptions.languages ?? defaultLanguages;
6736
+ const explicitLanguages = monacoOptions.languages;
6737
+ const languages$1 = explicitLanguages ?? defaultLanguages;
6499
6738
  const MAX_HEIGHT = monacoOptions.MAX_HEIGHT ?? 500;
6500
6739
  const autoScrollOnUpdate = monacoOptions.autoScrollOnUpdate ?? true;
6501
6740
  const autoScrollInitial = monacoOptions.autoScrollInitial ?? true;
@@ -6584,10 +6823,27 @@ function useMonaco(monacoOptions = {}) {
6584
6823
  console.warn("onThemeChange callback threw an error:", err);
6585
6824
  }
6586
6825
  }
6587
- async function ensureThemeRegistered(themeName) {
6826
+ function normalizeLanguage(language) {
6827
+ if (!language) return null;
6828
+ return processedLanguage(language) || language;
6829
+ }
6830
+ function resolveCreateLanguages(primaryLanguage) {
6831
+ const primary = normalizeLanguage(primaryLanguage);
6832
+ if (Array.isArray(explicitLanguages) && explicitLanguages.length) {
6833
+ const set = /* @__PURE__ */ new Set();
6834
+ for (const language of explicitLanguages) {
6835
+ const normalized = normalizeLanguage(language);
6836
+ if (normalized) set.add(normalized);
6837
+ }
6838
+ if (primary) set.add(primary);
6839
+ return Array.from(set);
6840
+ }
6841
+ return primary ? [primary] : ["typescript"];
6842
+ }
6843
+ async function ensureThemeRegistered(themeName, requestedLanguages = languages$1) {
6588
6844
  const availableNames = themes.map((t) => typeof t === "string" ? t : t.name);
6589
6845
  const list = availableNames.includes(themeName) ? themes : themes.concat(themeName);
6590
- await registerMonacoThemes(list, languages$1);
6846
+ await registerMonacoThemes(list, requestedLanguages);
6591
6847
  }
6592
6848
  function resolveRequestedThemeName() {
6593
6849
  return requestedThemeName ?? globalRequestedThemeName ?? monacoOptions.theme ?? currentTheme.value;
@@ -6664,11 +6920,12 @@ function useMonaco(monacoOptions = {}) {
6664
6920
  queuedEditorUpdateDuringCreate = null;
6665
6921
  disposeAllPendingCreateDisposables();
6666
6922
  }
6667
- async function resolveCreateThemeName(requestId, kind) {
6923
+ async function resolveCreateThemeName(requestId, kind, primaryLanguage) {
6668
6924
  let themeName = resolveRequestedThemeName();
6925
+ const createLanguages = resolveCreateLanguages(primaryLanguage);
6669
6926
  while (true) {
6670
6927
  assertCreateStillActive(requestId, kind);
6671
- await ensureThemeRegistered(themeName);
6928
+ await ensureThemeRegistered(themeName, createLanguages);
6672
6929
  assertCreateStillActive(requestId, kind);
6673
6930
  const latestThemeName = resolveRequestedThemeName();
6674
6931
  if (latestThemeName === themeName) return themeName;
@@ -6687,7 +6944,7 @@ function useMonaco(monacoOptions = {}) {
6687
6944
  if (requestDisposables.length) pendingCreateDisposables.set(requestId, requestDisposables);
6688
6945
  let nextEditorMgr = null;
6689
6946
  try {
6690
- const initialThemeName = await resolveCreateThemeName(requestId, "editor");
6947
+ const initialThemeName = await resolveCreateThemeName(requestId, "editor", language);
6691
6948
  nextEditorMgr = new EditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, monacoOptions.revealDebounceMs, monacoOptions.updateThrottleMs);
6692
6949
  const nextEditorView = await nextEditorMgr.createEditor(container, code, language, initialThemeName);
6693
6950
  assertCreateStillActive(requestId, "editor");
@@ -6734,7 +6991,7 @@ function useMonaco(monacoOptions = {}) {
6734
6991
  if (requestDisposables.length) pendingCreateDisposables.set(requestId, requestDisposables);
6735
6992
  let nextDiffMgr = null;
6736
6993
  try {
6737
- const initialThemeName = await resolveCreateThemeName(requestId, "diff");
6994
+ const initialThemeName = await resolveCreateThemeName(requestId, "diff", language);
6738
6995
  nextDiffMgr = new DiffEditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, diffAutoScroll, monacoOptions.revealDebounceMs, monacoOptions.diffUpdateThrottleMs);
6739
6996
  const nextDiffEditorView = await nextDiffMgr.createDiffEditor(container, originalCode, modifiedCode, language, initialThemeName);
6740
6997
  assertCreateStillActive(requestId, "diff");