@tracecode/harness 0.5.0 → 0.6.0

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +67 -80
  3. package/README.md +31 -4
  4. package/dist/browser.cjs +974 -19
  5. package/dist/browser.cjs.map +1 -1
  6. package/dist/browser.d.cts +3 -2
  7. package/dist/browser.d.ts +3 -2
  8. package/dist/browser.js +974 -19
  9. package/dist/browser.js.map +1 -1
  10. package/dist/cli.cjs +24 -0
  11. package/dist/cli.cjs.map +1 -1
  12. package/dist/cli.js +24 -0
  13. package/dist/cli.js.map +1 -1
  14. package/dist/core.cjs +611 -4
  15. package/dist/core.cjs.map +1 -1
  16. package/dist/core.d.cts +20 -6
  17. package/dist/core.d.ts +20 -6
  18. package/dist/core.js +605 -4
  19. package/dist/core.js.map +1 -1
  20. package/dist/index.cjs +1055 -52
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +3 -3
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.js +1049 -52
  25. package/dist/index.js.map +1 -1
  26. package/dist/internal/browser.cjs +211 -0
  27. package/dist/internal/browser.cjs.map +1 -1
  28. package/dist/internal/browser.d.cts +62 -6
  29. package/dist/internal/browser.d.ts +62 -6
  30. package/dist/internal/browser.js +210 -0
  31. package/dist/internal/browser.js.map +1 -1
  32. package/dist/javascript.cjs +37 -19
  33. package/dist/javascript.cjs.map +1 -1
  34. package/dist/javascript.d.cts +2 -2
  35. package/dist/javascript.d.ts +2 -2
  36. package/dist/javascript.js +37 -19
  37. package/dist/javascript.js.map +1 -1
  38. package/dist/python.cjs +14 -14
  39. package/dist/python.cjs.map +1 -1
  40. package/dist/python.d.cts +8 -8
  41. package/dist/python.d.ts +8 -8
  42. package/dist/python.js +14 -14
  43. package/dist/python.js.map +1 -1
  44. package/dist/{runtime-types-DtaaAhHL.d.ts → runtime-types-89nchXlY.d.cts} +8 -4
  45. package/dist/{runtime-types--lBQ6rYu.d.cts → runtime-types-CCQ-ZLc9.d.ts} +8 -4
  46. package/dist/{types-DwIYM3Ku.d.cts → types-zyvpJKCi.d.cts} +1 -0
  47. package/dist/{types-DwIYM3Ku.d.ts → types-zyvpJKCi.d.ts} +1 -0
  48. package/package.json +12 -6
  49. package/workers/java/.build/classes/harness/browser/JavaRewriteLibrary.class +0 -0
  50. package/workers/java/java-worker.js +712 -0
  51. package/workers/java/src/harness/browser/JavaRewriteLibrary.java +54 -0
  52. package/workers/javascript/javascript-worker.js +343 -63
  53. package/workers/python/generated-python-harness-snippets.js +3 -3
  54. package/workers/python/pyodide-worker.js +419 -68
  55. package/workers/python/runtime-core.js +52 -3
  56. package/workers/vendor/java-browser-spike-helper.jar +0 -0
  57. package/workers/vendor/java-practice-rewriter.jar +0 -0
  58. package/workers/vendor/java-rewrite-bridge.jar +0 -0
  59. package/workers/vendor/javaparser-core-3.25.10.jar +0 -0
  60. package/workers/vendor/jdk.compiler-17.jar +0 -0
package/dist/index.cjs CHANGED
@@ -39,9 +39,13 @@ __export(src_exports, {
39
39
  TEMPLATE_PYTHON_TRACE_SERIALIZE_FUNCTION: () => TEMPLATE_PYTHON_TRACE_SERIALIZE_FUNCTION,
40
40
  TYPESCRIPT_RUNTIME_DECLARATIONS: () => TYPESCRIPT_RUNTIME_DECLARATIONS,
41
41
  adaptJavaScriptTraceExecutionResult: () => adaptJavaScriptTraceExecutionResult,
42
+ adaptJavaSpikeTraceExecutionResult: () => adaptJavaTraceExecutionResult,
43
+ adaptJavaTraceExecutionResult: () => adaptJavaTraceExecutionResult,
42
44
  adaptPythonTraceExecutionResult: () => adaptPythonTraceExecutionResult,
43
45
  adaptTraceExecutionResult: () => adaptTraceExecutionResult,
44
46
  assertRuntimeRequestSupported: () => assertRuntimeRequestSupported,
47
+ buildJavaExecutionResult: () => buildJavaExecutionResult,
48
+ buildJavaSpikeExecutionResult: () => buildJavaExecutionResult,
45
49
  createBrowserHarness: () => createBrowserHarness,
46
50
  executeJavaScriptCode: () => executeJavaScriptCode,
47
51
  executeJavaScriptWithTracing: () => executeJavaScriptWithTracing,
@@ -53,6 +57,8 @@ __export(src_exports, {
53
57
  getSupportedLanguageProfiles: () => getSupportedLanguageProfiles,
54
58
  identifyConversions: () => identifyConversions,
55
59
  isLanguageSupported: () => isLanguageSupported,
60
+ normalizeJavaSpikeTraceContract: () => normalizeJavaTraceContract,
61
+ normalizeJavaTraceContract: () => normalizeJavaTraceContract,
56
62
  normalizeRuntimeTraceContract: () => normalizeRuntimeTraceContract,
57
63
  resolveBrowserHarnessAssets: () => resolveBrowserHarnessAssets,
58
64
  stableStringifyRuntimeTraceContract: () => stableStringifyRuntimeTraceContract,
@@ -63,7 +69,7 @@ __export(src_exports, {
63
69
  module.exports = __toCommonJS(src_exports);
64
70
 
65
71
  // packages/harness-core/src/trace-contract.ts
66
- var RUNTIME_TRACE_CONTRACT_SCHEMA_VERSION = "2026-03-13";
72
+ var RUNTIME_TRACE_CONTRACT_SCHEMA_VERSION = "2026-04-21";
67
73
  var TRACE_EVENTS = /* @__PURE__ */ new Set([
68
74
  "line",
69
75
  "call",
@@ -184,7 +190,39 @@ function normalizeAccesses(accesses) {
184
190
  }
185
191
  return payload;
186
192
  }).filter((access) => access !== null);
187
- return normalized.length > 0 ? normalized : void 0;
193
+ if (normalized.length === 0) {
194
+ return void 0;
195
+ }
196
+ const statsByVariable = /* @__PURE__ */ new Map();
197
+ for (const access of normalized) {
198
+ const stats = statsByVariable.get(access.variable) ?? { hasCellRead: false, hasCellWrite: false };
199
+ if (access.kind === "cell-read") stats.hasCellRead = true;
200
+ if (access.kind === "cell-write") stats.hasCellWrite = true;
201
+ statsByVariable.set(access.variable, stats);
202
+ }
203
+ const deduped = /* @__PURE__ */ new Set();
204
+ const collapsed = normalized.filter((access) => {
205
+ const stats = statsByVariable.get(access.variable);
206
+ if (access.kind === "indexed-read" && (stats?.hasCellRead || stats?.hasCellWrite)) {
207
+ return false;
208
+ }
209
+ if (access.kind === "indexed-write" && stats?.hasCellWrite) {
210
+ return false;
211
+ }
212
+ const key = JSON.stringify([
213
+ access.variable,
214
+ access.kind,
215
+ access.indices ?? null,
216
+ access.pathDepth ?? null,
217
+ access.method ?? null
218
+ ]);
219
+ if (deduped.has(key)) {
220
+ return false;
221
+ }
222
+ deduped.add(key);
223
+ return true;
224
+ });
225
+ return collapsed.length > 0 ? collapsed : void 0;
188
226
  }
189
227
  function normalizeRecord(value) {
190
228
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
@@ -248,8 +286,64 @@ function normalizeTraceStep(step) {
248
286
  ...normalizedVisualization ? { visualization: normalizedVisualization } : {}
249
287
  };
250
288
  }
289
+ function collapseTraceAccessNoise(trace) {
290
+ const variablesWithCellAccess = /* @__PURE__ */ new Set();
291
+ const accessStatsByVariable = /* @__PURE__ */ new Map();
292
+ for (const step of trace) {
293
+ for (const access of step.accesses ?? []) {
294
+ const stats = accessStatsByVariable.get(access.variable) ?? {
295
+ hasCellRead: false,
296
+ hasCellWrite: false,
297
+ hasMutatingCall: false,
298
+ hasIndexedWrite: false
299
+ };
300
+ if (access.kind === "cell-read" || access.kind === "cell-write") {
301
+ variablesWithCellAccess.add(access.variable);
302
+ }
303
+ if (access.kind === "cell-read") stats.hasCellRead = true;
304
+ if (access.kind === "cell-write") stats.hasCellWrite = true;
305
+ if (access.kind === "mutating-call") stats.hasMutatingCall = true;
306
+ if (access.kind === "indexed-write") stats.hasIndexedWrite = true;
307
+ accessStatsByVariable.set(access.variable, stats);
308
+ }
309
+ }
310
+ if (variablesWithCellAccess.size === 0) {
311
+ return trace;
312
+ }
313
+ return trace.map((step) => {
314
+ if (!step.accesses?.length) {
315
+ return step;
316
+ }
317
+ const filtered = step.accesses.filter((access) => {
318
+ const stats = accessStatsByVariable.get(access.variable);
319
+ if (variablesWithCellAccess.has(access.variable)) {
320
+ return access.kind !== "indexed-read" && access.kind !== "indexed-write";
321
+ }
322
+ if (access.kind === "mutating-call" && stats?.hasIndexedWrite && !stats.hasCellRead && !stats.hasCellWrite) {
323
+ return false;
324
+ }
325
+ if (access.kind === "indexed-read" && stats?.hasMutatingCall && !stats.hasIndexedWrite && !stats.hasCellRead && !stats.hasCellWrite) {
326
+ return false;
327
+ }
328
+ return true;
329
+ });
330
+ if (filtered.length === step.accesses.length) {
331
+ return step;
332
+ }
333
+ return {
334
+ ...step,
335
+ ...filtered.length > 0 ? { accesses: filtered } : {},
336
+ ...filtered.length === 0 ? { accesses: void 0 } : {}
337
+ };
338
+ });
339
+ }
251
340
  function normalizeRuntimeTraceContract(language, result) {
252
- const normalizedTrace = Array.isArray(result.trace) ? result.trace.map(normalizeTraceStep) : [];
341
+ const rawNormalizedTrace = collapseTraceAccessNoise(
342
+ Array.isArray(result.trace) ? result.trace.map(normalizeTraceStep) : []
343
+ );
344
+ const maxTraceSteps = typeof result.maxTraceSteps === "number" && Number.isFinite(result.maxTraceSteps) ? Math.max(1, Math.floor(result.maxTraceSteps)) : void 0;
345
+ const traceWasClipped = maxTraceSteps !== void 0 && rawNormalizedTrace.length > maxTraceSteps;
346
+ const normalizedTrace = traceWasClipped && maxTraceSteps !== void 0 ? rawNormalizedTrace.slice(0, maxTraceSteps) : rawNormalizedTrace;
253
347
  const lineEventCount = typeof result.lineEventCount === "number" && Number.isFinite(result.lineEventCount) ? Math.floor(result.lineEventCount) : normalizedTrace.filter((step) => step.event === "line").length;
254
348
  const normalizedConsole = Array.isArray(result.consoleOutput) ? result.consoleOutput.map((line) => String(line)) : [];
255
349
  return {
@@ -261,7 +355,7 @@ function normalizeRuntimeTraceContract(language, result) {
261
355
  ...typeof result.errorLine === "number" && Number.isFinite(result.errorLine) ? { errorLine: Math.floor(result.errorLine) } : {},
262
356
  consoleOutput: normalizedConsole,
263
357
  trace: normalizedTrace,
264
- ...result.traceLimitExceeded !== void 0 ? { traceLimitExceeded: Boolean(result.traceLimitExceeded) } : {},
358
+ ...result.traceLimitExceeded !== void 0 || traceWasClipped ? { traceLimitExceeded: Boolean(result.traceLimitExceeded) || traceWasClipped } : {},
265
359
  ...typeof result.timeoutReason === "string" && result.timeoutReason.length > 0 ? { timeoutReason: result.timeoutReason } : {},
266
360
  lineEventCount: Math.max(0, lineEventCount),
267
361
  traceStepCount: normalizedTrace.length
@@ -320,6 +414,513 @@ function adaptJavaScriptTraceExecutionResult(language, result) {
320
414
  return adaptTraceExecutionResult(language, result);
321
415
  }
322
416
 
417
+ // packages/harness-core/src/trace-adapters/java.ts
418
+ function parseScalar(raw) {
419
+ if (raw === "null") return null;
420
+ if (raw === "true") return true;
421
+ if (raw === "false") return false;
422
+ if (/^-?\d+$/.test(raw)) return Number.parseInt(raw, 10);
423
+ if (/^-?\d+\.\d+$/.test(raw)) return Number.parseFloat(raw);
424
+ if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("[") && raw.endsWith("]") || raw.startsWith("{") && raw.endsWith("}")) {
425
+ try {
426
+ return JSON.parse(raw);
427
+ } catch {
428
+ }
429
+ }
430
+ return raw;
431
+ }
432
+ function parseKeyValuePairs(fragment) {
433
+ const variables = {};
434
+ const matches = Array.from(fragment.matchAll(/\b([A-Za-z_][A-Za-z0-9_.]*)=/g));
435
+ for (let index = 0; index < matches.length; index += 1) {
436
+ const match = matches[index];
437
+ const rawKey = match[1];
438
+ const valueStart = (match.index ?? 0) + match[0].length;
439
+ const valueEnd = index + 1 < matches.length ? matches[index + 1].index ?? fragment.length : fragment.length;
440
+ const rawValue = fragment.slice(valueStart, valueEnd).trim();
441
+ if (!rawKey || rawValue === void 0) continue;
442
+ if (rawKey === "method") continue;
443
+ variables[rawKey.replaceAll(".", "_")] = parseScalar(rawValue);
444
+ }
445
+ return variables;
446
+ }
447
+ function extractLineMetadata(event) {
448
+ const match = event.match(/^line=(\d+)(?:\s+(.*))?$/);
449
+ if (!match) {
450
+ return { line: 1, payload: event };
451
+ }
452
+ return {
453
+ line: Number.parseInt(match[1], 10),
454
+ payload: match[2] ?? ""
455
+ };
456
+ }
457
+ function stripInlineComments(line, inBlockComment) {
458
+ let result = "";
459
+ let index = 0;
460
+ let inBlock = inBlockComment;
461
+ while (index < line.length) {
462
+ const current = line[index];
463
+ const next = index + 1 < line.length ? line[index + 1] : "";
464
+ if (inBlock) {
465
+ if (current === "*" && next === "/") {
466
+ inBlock = false;
467
+ index += 2;
468
+ continue;
469
+ }
470
+ index += 1;
471
+ continue;
472
+ }
473
+ if (current === "/" && next === "*") {
474
+ inBlock = true;
475
+ index += 2;
476
+ continue;
477
+ }
478
+ if (current === "/" && next === "/") {
479
+ break;
480
+ }
481
+ result += current;
482
+ index += 1;
483
+ }
484
+ return { text: result, inBlockComment: inBlock };
485
+ }
486
+ function isMethodDeclarationLine(line) {
487
+ const trimmed = line.trim();
488
+ if (!trimmed) return false;
489
+ if (trimmed.startsWith("@")) return false;
490
+ if (!trimmed.includes("(") || !trimmed.includes(")")) return false;
491
+ if (trimmed.endsWith(";")) return false;
492
+ if (trimmed.includes("->")) return false;
493
+ if (/^(?:if|for|while|switch|catch|do|try|else|return|throw|new)\b/.test(trimmed)) {
494
+ return false;
495
+ }
496
+ if (!/[A-Za-z_][A-Za-z0-9_]*\s*\([^{};]*\)/.test(trimmed)) {
497
+ return false;
498
+ }
499
+ return /(?:\{\s*)?$/.test(trimmed);
500
+ }
501
+ function buildLineRemap(sourceText) {
502
+ if (typeof sourceText !== "string" || sourceText.length === 0) {
503
+ return null;
504
+ }
505
+ const lines = sourceText.split(/\r?\n/);
506
+ const executable = /* @__PURE__ */ new Set();
507
+ let inBlockComment = false;
508
+ for (let index = 0; index < lines.length; index += 1) {
509
+ const { text, inBlockComment: nextInBlockComment } = stripInlineComments(lines[index] ?? "", inBlockComment);
510
+ inBlockComment = nextInBlockComment;
511
+ if (text.trim().length > 0) {
512
+ executable.add(index + 1);
513
+ }
514
+ }
515
+ if (executable.size === 0) {
516
+ return null;
517
+ }
518
+ const nextExecutableAtOrAfter = new Array(lines.length + 2).fill(null);
519
+ let nextExecutable = null;
520
+ for (let line = lines.length; line >= 1; line -= 1) {
521
+ if (executable.has(line)) {
522
+ nextExecutable = line;
523
+ }
524
+ nextExecutableAtOrAfter[line] = nextExecutable;
525
+ }
526
+ const previousExecutableAtOrBefore = new Array(lines.length + 2).fill(null);
527
+ let previousExecutable = null;
528
+ for (let line = 1; line <= lines.length; line += 1) {
529
+ if (executable.has(line)) {
530
+ previousExecutable = line;
531
+ }
532
+ previousExecutableAtOrBefore[line] = previousExecutable;
533
+ }
534
+ const remap = /* @__PURE__ */ new Map();
535
+ for (let line = 1; line <= lines.length; line += 1) {
536
+ if (executable.has(line)) continue;
537
+ const forward = nextExecutableAtOrAfter[line];
538
+ const backward = previousExecutableAtOrBefore[line];
539
+ const target = forward ?? backward;
540
+ if (target !== null && target !== line) {
541
+ remap.set(line, target);
542
+ }
543
+ }
544
+ return remap;
545
+ }
546
+ function buildMethodDeclarationLineSet(sourceText) {
547
+ if (typeof sourceText !== "string" || sourceText.length === 0) {
548
+ return null;
549
+ }
550
+ const declarationLines = /* @__PURE__ */ new Set();
551
+ const lines = sourceText.split(/\r?\n/);
552
+ let inBlockComment = false;
553
+ for (let index = 0; index < lines.length; index += 1) {
554
+ const { text, inBlockComment: nextInBlockComment } = stripInlineComments(lines[index] ?? "", inBlockComment);
555
+ inBlockComment = nextInBlockComment;
556
+ if (isMethodDeclarationLine(text)) {
557
+ declarationLines.add(index + 1);
558
+ }
559
+ }
560
+ return declarationLines;
561
+ }
562
+ function parseAccessEvent(payload) {
563
+ const isEphemeralOutputArrayName = (name) => /^(output|outputs)$/i.test(name);
564
+ const cellRead = payload.match(/^access ([A-Za-z_][A-Za-z0-9_]*)\[(\d+)\]\[(\d+)\]=(.+)$/);
565
+ if (cellRead) {
566
+ return [{
567
+ variable: cellRead[1],
568
+ kind: "cell-read",
569
+ indices: [Number.parseInt(cellRead[2], 10), Number.parseInt(cellRead[3], 10)],
570
+ pathDepth: 2
571
+ }];
572
+ }
573
+ const indexedRead = payload.match(/^access ([A-Za-z_][A-Za-z0-9_]*)\[(\d+)\]=(.+)$/);
574
+ if (indexedRead) {
575
+ return [{
576
+ variable: indexedRead[1],
577
+ kind: "indexed-read",
578
+ indices: [Number.parseInt(indexedRead[2], 10)],
579
+ pathDepth: 1
580
+ }];
581
+ }
582
+ const cellWrite = payload.match(/^write-array ([A-Za-z_][A-Za-z0-9_]*)\[(\d+)\]\[(\d+)\]=(.+)$/);
583
+ if (cellWrite) {
584
+ return [{
585
+ variable: cellWrite[1],
586
+ kind: "cell-write",
587
+ indices: [Number.parseInt(cellWrite[2], 10), Number.parseInt(cellWrite[3], 10)],
588
+ pathDepth: 2
589
+ }];
590
+ }
591
+ const indexedWrite = payload.match(/^write-array ([A-Za-z_][A-Za-z0-9_]*)\[(\d+)\]=(.+)$/);
592
+ if (indexedWrite) {
593
+ if (isEphemeralOutputArrayName(indexedWrite[1])) {
594
+ return void 0;
595
+ }
596
+ return [{
597
+ variable: indexedWrite[1],
598
+ kind: "indexed-write",
599
+ indices: [Number.parseInt(indexedWrite[2], 10)],
600
+ pathDepth: 1
601
+ }];
602
+ }
603
+ const mutatingCall = payload.match(/^mutate ([A-Za-z_][A-Za-z0-9_]*) method=([A-Za-z_][A-Za-z0-9_]*)$/);
604
+ if (mutatingCall) {
605
+ return [{
606
+ variable: mutatingCall[1],
607
+ kind: "mutating-call",
608
+ method: mutatingCall[2],
609
+ pathDepth: 1
610
+ }];
611
+ }
612
+ return void 0;
613
+ }
614
+ function parseStructureState(payload) {
615
+ const match = payload.match(/^state (linked-list|tree) ([A-Za-z_][A-Za-z0-9_]*)=(.+)$/);
616
+ if (!match) return null;
617
+ return {
618
+ structure: match[1],
619
+ variable: match[2],
620
+ value: JSON.parse(match[3])
621
+ };
622
+ }
623
+ function parseObjectState(payload) {
624
+ const match = payload.match(/^object-state ([A-Za-z_][A-Za-z0-9_]*)=(.+)$/);
625
+ if (!match) return null;
626
+ return {
627
+ variable: match[1],
628
+ visualization: JSON.parse(match[2])
629
+ };
630
+ }
631
+ function parseObjectFieldEvent(payload) {
632
+ const match = payload.match(/^(access|write) ([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)=(.+)$/);
633
+ if (!match) return null;
634
+ return {
635
+ variable: match[2],
636
+ field: match[3],
637
+ value: parseScalar(match[4])
638
+ };
639
+ }
640
+ function buildFieldVisualization(event) {
641
+ return {
642
+ objectKinds: {
643
+ [event.variable]: "object"
644
+ },
645
+ hashMaps: [
646
+ {
647
+ name: event.variable,
648
+ kind: "object",
649
+ objectClassName: event.field === "next" || event.field === "prev" ? "ListNode" : event.field === "left" || event.field === "right" ? "TreeNode" : void 0,
650
+ objectId: `${event.variable}-object`,
651
+ highlightedKey: event.field,
652
+ entries: [{ key: event.field, value: event.value, highlight: true }]
653
+ }
654
+ ]
655
+ };
656
+ }
657
+ function callStacksEqual(left, right) {
658
+ return JSON.stringify(left ?? []) === JSON.stringify(right ?? []);
659
+ }
660
+ function mergeVisualizationPayloads(left, right) {
661
+ if (!left) return right;
662
+ if (!right) return left;
663
+ return {
664
+ ...left,
665
+ ...right,
666
+ objectKinds: {
667
+ ...left.objectKinds ?? {},
668
+ ...right.objectKinds ?? {}
669
+ },
670
+ hashMaps: [
671
+ ...left.hashMaps ?? [],
672
+ ...right.hashMaps ?? []
673
+ ]
674
+ };
675
+ }
676
+ function maybeMergeConsecutiveLineStep(trace, nextStep) {
677
+ if (nextStep.event !== "line") {
678
+ return false;
679
+ }
680
+ const previous = trace.at(-1);
681
+ if (!previous || previous.event !== "line") {
682
+ return false;
683
+ }
684
+ if (previous.line !== nextStep.line || previous.function !== nextStep.function) {
685
+ return false;
686
+ }
687
+ if (!callStacksEqual(previous.callStack, nextStep.callStack)) {
688
+ return false;
689
+ }
690
+ previous.variables = { ...previous.variables ?? {}, ...nextStep.variables ?? {} };
691
+ if (nextStep.accesses?.length) {
692
+ previous.accesses = [...previous.accesses ?? [], ...nextStep.accesses];
693
+ }
694
+ previous.visualization = mergeVisualizationPayloads(previous.visualization, nextStep.visualization);
695
+ return true;
696
+ }
697
+ function filterStructuredVariables(variables) {
698
+ if (!variables) {
699
+ return void 0;
700
+ }
701
+ const isEphemeralOutputArrayName = (name) => /^(output|outputs)$/i.test(name);
702
+ const entries = Object.entries(variables).filter(([name, value]) => {
703
+ if (value === null || typeof value !== "object") {
704
+ return false;
705
+ }
706
+ if (!Array.isArray(value)) {
707
+ return true;
708
+ }
709
+ if (Array.isArray(value[0])) {
710
+ return true;
711
+ }
712
+ return !isEphemeralOutputArrayName(name);
713
+ });
714
+ if (entries.length === 0) {
715
+ return void 0;
716
+ }
717
+ return Object.fromEntries(entries);
718
+ }
719
+ function appendJavaTraceStep(trace, step, pendingAccesses) {
720
+ const nextStep = pendingAccesses.length > 0 ? { ...step, accesses: [...pendingAccesses] } : step;
721
+ pendingAccesses.length = 0;
722
+ if (!maybeMergeConsecutiveLineStep(trace, nextStep)) {
723
+ trace.push(nextStep);
724
+ }
725
+ }
726
+ function mergeIntoPreviousMatchingLineStep(trace, line, currentFunction, currentCallStack, patch) {
727
+ const candidate = trace.at(-1);
728
+ if (!candidate || candidate.event !== "line") {
729
+ return false;
730
+ }
731
+ if (candidate.line !== line || candidate.function !== currentFunction) {
732
+ return false;
733
+ }
734
+ if (!callStacksEqual(candidate.callStack, currentCallStack)) {
735
+ return false;
736
+ }
737
+ candidate.variables = { ...candidate.variables ?? {}, ...patch.variables ?? {} };
738
+ if (patch.accesses?.length) {
739
+ candidate.accesses = [...candidate.accesses ?? [], ...patch.accesses];
740
+ }
741
+ candidate.visualization = mergeVisualizationPayloads(candidate.visualization, patch.visualization);
742
+ return true;
743
+ }
744
+ function mergeAccessesIntoPreviousMatchingLineStep(trace, line, currentFunction, currentCallStack, accesses) {
745
+ return mergeIntoPreviousMatchingLineStep(trace, line, currentFunction, currentCallStack, {
746
+ variables: void 0,
747
+ accesses,
748
+ visualization: void 0
749
+ });
750
+ }
751
+ function eventsToRawTrace(events, sourceText) {
752
+ const trace = [];
753
+ const variables = {};
754
+ const objectKinds = {};
755
+ const stack = [];
756
+ const pendingAccesses = [];
757
+ let currentFunction = "<module>";
758
+ const lineRemap = buildLineRemap(sourceText);
759
+ const declarationLines = buildMethodDeclarationLineSet(sourceText);
760
+ for (const rawEvent of events) {
761
+ if (rawEvent === "clear" || rawEvent === "reset") continue;
762
+ const metadata = extractLineMetadata(rawEvent);
763
+ const line = lineRemap?.get(metadata.line) ?? metadata.line;
764
+ const payload = metadata.payload;
765
+ const isDeclarationLine = declarationLines?.has(line) === true;
766
+ if (payload.startsWith("call ")) {
767
+ const match = payload.match(/^call\s+(\S+)(?:\s+(.*))?$/);
768
+ const functionName = match?.[1] ?? currentFunction;
769
+ const argsFragment = match?.[2] ?? "";
770
+ Object.assign(variables, parseKeyValuePairs(argsFragment));
771
+ currentFunction = functionName || currentFunction;
772
+ stack.push({ function: currentFunction, line });
773
+ appendJavaTraceStep(trace, {
774
+ line,
775
+ event: "call",
776
+ function: currentFunction,
777
+ variables: { ...variables },
778
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} }))
779
+ }, pendingAccesses);
780
+ continue;
781
+ }
782
+ if (payload.startsWith("return ")) {
783
+ const match = payload.match(/^return\s+(\S+)$/);
784
+ const functionName = match?.[1] ?? currentFunction;
785
+ const returnVariables = functionName === "<module>" ? { ...variables } : filterStructuredVariables(variables) ?? {};
786
+ appendJavaTraceStep(trace, {
787
+ line,
788
+ event: "return",
789
+ function: functionName || currentFunction,
790
+ variables: returnVariables,
791
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} }))
792
+ }, pendingAccesses);
793
+ stack.pop();
794
+ currentFunction = stack[stack.length - 1]?.function ?? "<module>";
795
+ continue;
796
+ }
797
+ if (isDeclarationLine) {
798
+ continue;
799
+ }
800
+ if (payload.length === 0) {
801
+ appendJavaTraceStep(trace, {
802
+ line,
803
+ event: "line",
804
+ function: currentFunction,
805
+ variables: { ...variables },
806
+ ...stack.length > 0 ? { callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })) } : {}
807
+ }, pendingAccesses);
808
+ continue;
809
+ }
810
+ const structureState = parseStructureState(payload);
811
+ if (structureState) {
812
+ variables[structureState.variable] = structureState.value;
813
+ objectKinds[structureState.variable] = structureState.structure;
814
+ appendJavaTraceStep(trace, {
815
+ line,
816
+ event: "line",
817
+ function: currentFunction,
818
+ variables: { ...variables },
819
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })),
820
+ visualization: {
821
+ objectKinds: { ...objectKinds }
822
+ }
823
+ }, pendingAccesses);
824
+ continue;
825
+ }
826
+ const objectState = parseObjectState(payload);
827
+ if (objectState) {
828
+ variables[objectState.variable] = { __ref__: objectState.visualization.objectId ?? `${objectState.variable}-object` };
829
+ appendJavaTraceStep(trace, {
830
+ line,
831
+ event: "line",
832
+ function: currentFunction,
833
+ variables: { ...variables },
834
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })),
835
+ visualization: {
836
+ objectKinds: { [objectState.variable]: "object" },
837
+ hashMaps: [objectState.visualization]
838
+ }
839
+ }, pendingAccesses);
840
+ continue;
841
+ }
842
+ const objectField = parseObjectFieldEvent(payload);
843
+ if (objectField) {
844
+ variables[objectField.variable] = { __ref__: `${objectField.variable}-object` };
845
+ const currentCallStack = stack.length > 0 ? stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })) : void 0;
846
+ if (mergeIntoPreviousMatchingLineStep(trace, line, currentFunction, currentCallStack, {
847
+ variables: { ...variables },
848
+ accesses: void 0,
849
+ visualization: buildFieldVisualization(objectField)
850
+ })) {
851
+ continue;
852
+ }
853
+ appendJavaTraceStep(trace, {
854
+ line,
855
+ event: "line",
856
+ function: currentFunction,
857
+ variables: { ...variables },
858
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })),
859
+ visualization: buildFieldVisualization(objectField)
860
+ }, pendingAccesses);
861
+ continue;
862
+ }
863
+ Object.assign(variables, parseKeyValuePairs(payload));
864
+ const accesses = parseAccessEvent(payload);
865
+ if (accesses) {
866
+ const currentCallStack = stack.length > 0 ? stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })) : void 0;
867
+ if (mergeAccessesIntoPreviousMatchingLineStep(trace, line, currentFunction, currentCallStack, accesses)) {
868
+ continue;
869
+ }
870
+ pendingAccesses.push(...accesses);
871
+ continue;
872
+ }
873
+ appendJavaTraceStep(trace, {
874
+ line,
875
+ event: "line",
876
+ function: currentFunction,
877
+ variables: { ...variables },
878
+ ...stack.length > 0 ? { callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })) } : {}
879
+ }, pendingAccesses);
880
+ }
881
+ if (pendingAccesses.length > 0 && trace.length > 0) {
882
+ const last = trace[trace.length - 1];
883
+ last.accesses = [...last.accesses ?? [], ...pendingAccesses];
884
+ }
885
+ return trace;
886
+ }
887
+ function buildJavaExecutionResult(output, events, executionTimeMs = 0, traceLimitExceeded, timeoutReason, maxTraceSteps, sourceText) {
888
+ const trace = eventsToRawTrace(events, sourceText);
889
+ return {
890
+ success: true,
891
+ output,
892
+ trace,
893
+ executionTimeMs,
894
+ consoleOutput: [],
895
+ ...traceLimitExceeded !== void 0 ? { traceLimitExceeded } : {},
896
+ ...maxTraceSteps !== void 0 ? { maxTraceSteps } : {},
897
+ ...timeoutReason ? { timeoutReason } : {},
898
+ lineEventCount: trace.filter((step) => step.event === "line").length,
899
+ traceStepCount: trace.length
900
+ };
901
+ }
902
+ function normalizeJavaTraceContract(result) {
903
+ const normalized = normalizeRuntimeTraceContract(
904
+ "java",
905
+ buildJavaExecutionResult(
906
+ result.output,
907
+ result.events,
908
+ 0,
909
+ result.traceLimitExceeded,
910
+ result.timeoutReason,
911
+ void 0,
912
+ result.sourceText
913
+ )
914
+ );
915
+ return {
916
+ ...normalized,
917
+ language: "java"
918
+ };
919
+ }
920
+ function adaptJavaTraceExecutionResult(result) {
921
+ return adaptTraceExecutionResult("java", result);
922
+ }
923
+
323
924
  // packages/harness-browser/src/javascript-worker-client.ts
324
925
  var EXECUTION_TIMEOUT_MS = 7e3;
325
926
  var INTERVIEW_MODE_TIMEOUT_MS = 5e3;
@@ -646,6 +1247,7 @@ var PYTHON_RUNTIME_PROFILE = {
646
1247
  maxTraceSteps: true,
647
1248
  maxLineEvents: true,
648
1249
  maxSingleLineHits: true,
1250
+ maxStoredEvents: true,
649
1251
  minimalTrace: true
650
1252
  },
651
1253
  fidelity: {
@@ -707,6 +1309,7 @@ var JAVASCRIPT_RUNTIME_PROFILE = {
707
1309
  maxTraceSteps: true,
708
1310
  maxLineEvents: true,
709
1311
  maxSingleLineHits: true,
1312
+ maxStoredEvents: true,
710
1313
  minimalTrace: true
711
1314
  },
712
1315
  fidelity: {
@@ -768,6 +1371,7 @@ var TYPESCRIPT_RUNTIME_PROFILE = {
768
1371
  maxTraceSteps: true,
769
1372
  maxLineEvents: true,
770
1373
  maxSingleLineHits: true,
1374
+ maxStoredEvents: true,
771
1375
  minimalTrace: true
772
1376
  },
773
1377
  fidelity: {
@@ -798,10 +1402,78 @@ var TYPESCRIPT_RUNTIME_PROFILE = {
798
1402
  }
799
1403
  }
800
1404
  };
1405
+ var JAVA_RUNTIME_PROFILE = {
1406
+ language: "java",
1407
+ maturity: "experimental",
1408
+ capabilities: {
1409
+ execution: {
1410
+ styles: {
1411
+ function: true,
1412
+ solutionMethod: true,
1413
+ opsClass: true,
1414
+ script: false,
1415
+ interviewMode: true
1416
+ },
1417
+ timeouts: {
1418
+ clientTimeouts: true,
1419
+ runtimeTimeouts: true
1420
+ }
1421
+ },
1422
+ tracing: {
1423
+ supported: true,
1424
+ events: {
1425
+ line: true,
1426
+ call: true,
1427
+ return: true,
1428
+ exception: true,
1429
+ stdout: false,
1430
+ timeout: true
1431
+ },
1432
+ controls: {
1433
+ maxTraceSteps: true,
1434
+ maxLineEvents: false,
1435
+ maxSingleLineHits: false,
1436
+ maxStoredEvents: true,
1437
+ minimalTrace: false
1438
+ },
1439
+ fidelity: {
1440
+ preciseLineMapping: true,
1441
+ stableFunctionNames: true,
1442
+ callStack: true
1443
+ }
1444
+ },
1445
+ diagnostics: {
1446
+ compileErrors: true,
1447
+ runtimeErrors: true,
1448
+ mappedErrorLines: false,
1449
+ stackTraces: true
1450
+ },
1451
+ structures: {
1452
+ treeNodeRefs: true,
1453
+ listNodeRefs: true,
1454
+ mapSerialization: true,
1455
+ setSerialization: true,
1456
+ graphSerialization: false,
1457
+ cycleReferences: true
1458
+ },
1459
+ visualization: {
1460
+ runtimePayloads: true,
1461
+ objectKinds: true,
1462
+ hashMaps: true,
1463
+ stepVisualization: true
1464
+ }
1465
+ },
1466
+ notes: [
1467
+ "Java currently supports the browser-local Java 17 lane for function, solution-method, and ops-class execution.",
1468
+ "Interview-mode Java reuses the same browser-local execution path and remains experimental in the first harness slice.",
1469
+ "Script-style Java is not enabled yet."
1470
+ ]
1471
+ };
801
1472
  var LANGUAGE_RUNTIME_PROFILES = {
802
1473
  python: PYTHON_RUNTIME_PROFILE,
803
1474
  javascript: JAVASCRIPT_RUNTIME_PROFILE,
804
- typescript: TYPESCRIPT_RUNTIME_PROFILE
1475
+ typescript: TYPESCRIPT_RUNTIME_PROFILE,
1476
+ java: JAVA_RUNTIME_PROFILE
805
1477
  };
806
1478
  var SUPPORTED_LANGUAGES = Object.freeze(
807
1479
  Object.keys(LANGUAGE_RUNTIME_PROFILES)
@@ -878,13 +1550,307 @@ function createJavaScriptRuntimeClient(runtimeLanguage, workerClient) {
878
1550
  return new JavaScriptRuntimeClient(runtimeLanguage, workerClient);
879
1551
  }
880
1552
 
1553
+ // packages/harness-browser/src/java-worker-client.ts
1554
+ var TRACING_TIMEOUT_MS2 = 25e3;
1555
+ var INIT_TIMEOUT_MS2 = 25e3;
1556
+ var MESSAGE_TIMEOUT_MS2 = 3e4;
1557
+ var WORKER_READY_TIMEOUT_MS2 = 1e4;
1558
+ var JavaWorkerClient = class {
1559
+ constructor(options) {
1560
+ this.options = options;
1561
+ this.debug = options.debug ?? process.env.NODE_ENV === "development";
1562
+ }
1563
+ worker = null;
1564
+ pendingMessages = /* @__PURE__ */ new Map();
1565
+ messageId = 0;
1566
+ isInitializing = false;
1567
+ initPromise = null;
1568
+ workerReadyPromise = null;
1569
+ workerReadyResolve = null;
1570
+ workerReadyReject = null;
1571
+ debug;
1572
+ isSupported() {
1573
+ return typeof Worker !== "undefined";
1574
+ }
1575
+ getWorker() {
1576
+ if (this.worker) return this.worker;
1577
+ if (!this.isSupported()) {
1578
+ throw new Error("Web Workers are not supported in this environment");
1579
+ }
1580
+ this.workerReadyPromise = new Promise((resolve, reject) => {
1581
+ this.workerReadyResolve = resolve;
1582
+ this.workerReadyReject = (error) => reject(error);
1583
+ });
1584
+ const workerUrl = this.debug && !this.options.workerUrl.includes("?") ? `${this.options.workerUrl}?dev=${Date.now()}` : this.options.workerUrl;
1585
+ this.worker = new Worker(workerUrl);
1586
+ this.worker.onmessage = (event) => {
1587
+ const { id, type, payload } = event.data;
1588
+ if (type === "worker-ready") {
1589
+ this.workerReadyResolve?.();
1590
+ this.workerReadyResolve = null;
1591
+ this.workerReadyReject = null;
1592
+ return;
1593
+ }
1594
+ if (!id) return;
1595
+ const pending = this.pendingMessages.get(id);
1596
+ if (!pending) return;
1597
+ this.pendingMessages.delete(id);
1598
+ if (pending.timeoutId) globalThis.clearTimeout(pending.timeoutId);
1599
+ if (type === "error") {
1600
+ pending.reject(new Error(payload.error));
1601
+ return;
1602
+ }
1603
+ pending.resolve(payload);
1604
+ };
1605
+ this.worker.onerror = (error) => {
1606
+ const workerError = new Error(error.message || "Java worker error");
1607
+ this.workerReadyReject?.(workerError);
1608
+ this.workerReadyResolve = null;
1609
+ this.workerReadyReject = null;
1610
+ for (const [, pending] of this.pendingMessages) {
1611
+ if (pending.timeoutId) globalThis.clearTimeout(pending.timeoutId);
1612
+ pending.reject(workerError);
1613
+ }
1614
+ this.pendingMessages.clear();
1615
+ this.terminateAndReset(workerError);
1616
+ };
1617
+ return this.worker;
1618
+ }
1619
+ async waitForWorkerReady() {
1620
+ const readyPromise = this.workerReadyPromise;
1621
+ if (!readyPromise) return;
1622
+ await new Promise((resolve, reject) => {
1623
+ let settled = false;
1624
+ const timeoutId = globalThis.setTimeout(() => {
1625
+ if (settled) return;
1626
+ settled = true;
1627
+ const timeoutError = new Error(
1628
+ `Java worker failed to initialize in time (${Math.round(WORKER_READY_TIMEOUT_MS2 / 1e3)}s)`
1629
+ );
1630
+ this.terminateAndReset(timeoutError);
1631
+ reject(timeoutError);
1632
+ }, WORKER_READY_TIMEOUT_MS2);
1633
+ readyPromise.then(() => {
1634
+ if (settled) return;
1635
+ settled = true;
1636
+ globalThis.clearTimeout(timeoutId);
1637
+ resolve();
1638
+ }).catch((error) => {
1639
+ if (settled) return;
1640
+ settled = true;
1641
+ globalThis.clearTimeout(timeoutId);
1642
+ reject(error instanceof Error ? error : new Error(String(error)));
1643
+ });
1644
+ });
1645
+ }
1646
+ async sendMessage(type, payload, timeoutMs = MESSAGE_TIMEOUT_MS2) {
1647
+ const worker = this.getWorker();
1648
+ await this.waitForWorkerReady();
1649
+ const id = String(++this.messageId);
1650
+ return new Promise((resolve, reject) => {
1651
+ this.pendingMessages.set(id, {
1652
+ resolve,
1653
+ reject
1654
+ });
1655
+ const timeoutId = globalThis.setTimeout(() => {
1656
+ const pending2 = this.pendingMessages.get(id);
1657
+ if (!pending2) return;
1658
+ this.pendingMessages.delete(id);
1659
+ pending2.reject(new Error(`Worker request timed out: ${type}`));
1660
+ }, timeoutMs);
1661
+ const pending = this.pendingMessages.get(id);
1662
+ if (pending) pending.timeoutId = timeoutId;
1663
+ worker.postMessage({ id, type, payload });
1664
+ });
1665
+ }
1666
+ async executeWithTimeout(executor, timeoutMs) {
1667
+ return new Promise((resolve, reject) => {
1668
+ let settled = false;
1669
+ const timeoutId = globalThis.setTimeout(() => {
1670
+ if (settled) return;
1671
+ settled = true;
1672
+ this.terminateAndReset();
1673
+ reject(
1674
+ new Error(
1675
+ `Java execution timed out after ${Math.round(timeoutMs / 1e3)} seconds.`
1676
+ )
1677
+ );
1678
+ }, timeoutMs);
1679
+ executor().then((result) => {
1680
+ if (settled) return;
1681
+ settled = true;
1682
+ globalThis.clearTimeout(timeoutId);
1683
+ resolve(result);
1684
+ }).catch((error) => {
1685
+ if (settled) return;
1686
+ settled = true;
1687
+ globalThis.clearTimeout(timeoutId);
1688
+ reject(error);
1689
+ });
1690
+ });
1691
+ }
1692
+ terminateAndReset(reason = new Error("Worker was terminated")) {
1693
+ this.workerReadyReject?.(reason);
1694
+ if (this.worker) {
1695
+ this.worker.terminate();
1696
+ this.worker = null;
1697
+ }
1698
+ this.initPromise = null;
1699
+ this.isInitializing = false;
1700
+ this.workerReadyPromise = null;
1701
+ this.workerReadyResolve = null;
1702
+ this.workerReadyReject = null;
1703
+ for (const [, pending] of this.pendingMessages) {
1704
+ if (pending.timeoutId) globalThis.clearTimeout(pending.timeoutId);
1705
+ pending.reject(reason);
1706
+ }
1707
+ this.pendingMessages.clear();
1708
+ }
1709
+ async init() {
1710
+ if (this.initPromise) return this.initPromise;
1711
+ if (this.isInitializing) {
1712
+ await new Promise((resolve) => globalThis.setTimeout(resolve, 100));
1713
+ return this.init();
1714
+ }
1715
+ this.isInitializing = true;
1716
+ this.initPromise = this.sendMessage("init", void 0, INIT_TIMEOUT_MS2);
1717
+ try {
1718
+ return await this.initPromise;
1719
+ } catch (error) {
1720
+ this.initPromise = null;
1721
+ throw error;
1722
+ } finally {
1723
+ this.isInitializing = false;
1724
+ }
1725
+ }
1726
+ async executeWithTracing(code, functionName, inputs, options, executionStyle) {
1727
+ await this.init();
1728
+ return this.executeWithTimeout(
1729
+ () => this.sendMessage(
1730
+ "execute-with-tracing",
1731
+ { code, functionName, inputs, options, executionStyle },
1732
+ TRACING_TIMEOUT_MS2 + 5e3
1733
+ ),
1734
+ TRACING_TIMEOUT_MS2
1735
+ );
1736
+ }
1737
+ async executeCode(code, functionName, inputs, options, executionStyle) {
1738
+ const result = await this.executeWithTracing(code, functionName, inputs, options, executionStyle);
1739
+ if (!result.success) {
1740
+ return {
1741
+ success: false,
1742
+ output: null,
1743
+ error: result.error ?? "Java execution failed",
1744
+ ...result.errorLine !== void 0 ? { errorLine: result.errorLine } : {},
1745
+ consoleOutput: result.consoleOutput
1746
+ };
1747
+ }
1748
+ return {
1749
+ success: true,
1750
+ output: result.output,
1751
+ consoleOutput: result.consoleOutput
1752
+ };
1753
+ }
1754
+ async executeCodeInterviewMode(code, functionName, inputs, options, executionStyle) {
1755
+ return this.executeCode(code, functionName, inputs, options, executionStyle);
1756
+ }
1757
+ terminate() {
1758
+ this.terminateAndReset();
1759
+ }
1760
+ };
1761
+
1762
+ // packages/harness-browser/src/java-runtime-client.ts
1763
+ var JavaRuntimeClient = class {
1764
+ constructor(workerClient) {
1765
+ this.workerClient = workerClient;
1766
+ }
1767
+ async init() {
1768
+ return this.workerClient.init();
1769
+ }
1770
+ async executeWithTracing(code, functionName, inputs, options, executionStyle = "function") {
1771
+ assertRuntimeRequestSupported(getLanguageRuntimeProfile("java"), {
1772
+ request: "trace",
1773
+ executionStyle,
1774
+ functionName
1775
+ });
1776
+ const rawResult = await this.workerClient.executeWithTracing(
1777
+ code,
1778
+ functionName ?? "",
1779
+ inputs,
1780
+ options,
1781
+ executionStyle
1782
+ );
1783
+ if (!rawResult.success) {
1784
+ return {
1785
+ success: false,
1786
+ error: rawResult.error ?? "Java tracing failed",
1787
+ ...rawResult.errorLine !== void 0 ? { errorLine: rawResult.errorLine } : {},
1788
+ trace: [],
1789
+ executionTimeMs: rawResult.executionTimeMs,
1790
+ consoleOutput: rawResult.consoleOutput,
1791
+ ...rawResult.traceLimitExceeded !== void 0 ? { traceLimitExceeded: rawResult.traceLimitExceeded } : {},
1792
+ ...rawResult.timeoutReason ? { timeoutReason: rawResult.timeoutReason } : {},
1793
+ lineEventCount: 0,
1794
+ traceStepCount: 0
1795
+ };
1796
+ }
1797
+ const adapted = adaptJavaTraceExecutionResult(
1798
+ buildJavaExecutionResult(
1799
+ rawResult.output,
1800
+ rawResult.events,
1801
+ rawResult.executionTimeMs,
1802
+ rawResult.traceLimitExceeded,
1803
+ rawResult.timeoutReason,
1804
+ void 0,
1805
+ rawResult.sourceText
1806
+ )
1807
+ );
1808
+ return {
1809
+ ...adapted,
1810
+ consoleOutput: rawResult.consoleOutput,
1811
+ executionTimeMs: rawResult.executionTimeMs
1812
+ };
1813
+ }
1814
+ async executeCode(code, functionName, inputs, executionStyle = "function") {
1815
+ assertRuntimeRequestSupported(getLanguageRuntimeProfile("java"), {
1816
+ request: "execute",
1817
+ executionStyle,
1818
+ functionName
1819
+ });
1820
+ return this.workerClient.executeCode(
1821
+ code,
1822
+ functionName,
1823
+ inputs,
1824
+ void 0,
1825
+ executionStyle
1826
+ );
1827
+ }
1828
+ async executeCodeInterviewMode(code, functionName, inputs, executionStyle = "function") {
1829
+ assertRuntimeRequestSupported(getLanguageRuntimeProfile("java"), {
1830
+ request: "interview",
1831
+ executionStyle,
1832
+ functionName
1833
+ });
1834
+ return this.workerClient.executeCodeInterviewMode(
1835
+ code,
1836
+ functionName,
1837
+ inputs,
1838
+ void 0,
1839
+ executionStyle
1840
+ );
1841
+ }
1842
+ };
1843
+ function createJavaRuntimeClient(workerClient) {
1844
+ return new JavaRuntimeClient(workerClient);
1845
+ }
1846
+
881
1847
  // packages/harness-browser/src/pyodide-worker-client.ts
882
1848
  var EXECUTION_TIMEOUT_MS2 = 1e4;
883
1849
  var INTERVIEW_MODE_TIMEOUT_MS2 = 5e3;
884
- var TRACING_TIMEOUT_MS2 = 3e4;
885
- var INIT_TIMEOUT_MS2 = 12e4;
886
- var MESSAGE_TIMEOUT_MS2 = 2e4;
887
- var WORKER_READY_TIMEOUT_MS2 = 1e4;
1850
+ var TRACING_TIMEOUT_MS3 = 3e4;
1851
+ var INIT_TIMEOUT_MS3 = 12e4;
1852
+ var MESSAGE_TIMEOUT_MS3 = 2e4;
1853
+ var WORKER_READY_TIMEOUT_MS3 = 1e4;
888
1854
  var PyodideWorkerClient = class {
889
1855
  constructor(options) {
890
1856
  this.options = options;
@@ -974,14 +1940,14 @@ var PyodideWorkerClient = class {
974
1940
  if (settled) return;
975
1941
  settled = true;
976
1942
  const timeoutError = new Error(
977
- `Python worker failed to initialize in time (${Math.round(WORKER_READY_TIMEOUT_MS2 / 1e3)}s)`
1943
+ `Python worker failed to initialize in time (${Math.round(WORKER_READY_TIMEOUT_MS3 / 1e3)}s)`
978
1944
  );
979
1945
  if (this.debug) {
980
- console.warn("[PyodideWorkerClient] worker-ready timeout", { timeoutMs: WORKER_READY_TIMEOUT_MS2 });
1946
+ console.warn("[PyodideWorkerClient] worker-ready timeout", { timeoutMs: WORKER_READY_TIMEOUT_MS3 });
981
1947
  }
982
1948
  this.terminateAndReset(timeoutError);
983
1949
  reject(timeoutError);
984
- }, WORKER_READY_TIMEOUT_MS2);
1950
+ }, WORKER_READY_TIMEOUT_MS3);
985
1951
  readyPromise.then(() => {
986
1952
  if (settled) return;
987
1953
  settled = true;
@@ -998,7 +1964,7 @@ var PyodideWorkerClient = class {
998
1964
  /**
999
1965
  * Send a message to the worker and wait for a response
1000
1966
  */
1001
- async sendMessage(type, payload, timeoutMs = MESSAGE_TIMEOUT_MS2) {
1967
+ async sendMessage(type, payload, timeoutMs = MESSAGE_TIMEOUT_MS3) {
1002
1968
  const worker = this.getWorker();
1003
1969
  await this.waitForWorkerReady();
1004
1970
  const id = String(++this.messageId);
@@ -1082,7 +2048,7 @@ var PyodideWorkerClient = class {
1082
2048
  this.isInitializing = true;
1083
2049
  this.initPromise = (async () => {
1084
2050
  try {
1085
- return await this.sendMessage("init", void 0, INIT_TIMEOUT_MS2);
2051
+ return await this.sendMessage("init", void 0, INIT_TIMEOUT_MS3);
1086
2052
  } catch (error) {
1087
2053
  const message = error instanceof Error ? error.message : String(error);
1088
2054
  const shouldRetry = message.includes("Worker request timed out: init") || message.includes("Worker was terminated") || message.includes("Worker error") || message.includes("failed to initialize in time");
@@ -1093,7 +2059,7 @@ var PyodideWorkerClient = class {
1093
2059
  console.warn("[PyodideWorkerClient] init failed, resetting worker and retrying once", { message });
1094
2060
  }
1095
2061
  this.terminateAndReset();
1096
- return this.sendMessage("init", void 0, INIT_TIMEOUT_MS2);
2062
+ return this.sendMessage("init", void 0, INIT_TIMEOUT_MS3);
1097
2063
  }
1098
2064
  })();
1099
2065
  try {
@@ -1120,9 +2086,9 @@ var PyodideWorkerClient = class {
1120
2086
  inputs,
1121
2087
  executionStyle,
1122
2088
  options
1123
- }, TRACING_TIMEOUT_MS2 + 5e3),
2089
+ }, TRACING_TIMEOUT_MS3 + 5e3),
1124
2090
  // Message timeout slightly longer than execution timeout
1125
- TRACING_TIMEOUT_MS2
2091
+ TRACING_TIMEOUT_MS3
1126
2092
  );
1127
2093
  } catch (error) {
1128
2094
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -1132,7 +2098,7 @@ var PyodideWorkerClient = class {
1132
2098
  success: false,
1133
2099
  error: errorMessage,
1134
2100
  trace: [],
1135
- executionTimeMs: TRACING_TIMEOUT_MS2,
2101
+ executionTimeMs: TRACING_TIMEOUT_MS3,
1136
2102
  consoleOutput: [],
1137
2103
  traceLimitExceeded: true,
1138
2104
  timeoutReason: "client-timeout",
@@ -1288,6 +2254,7 @@ var DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS = Object.freeze({
1288
2254
  pythonRuntimeCore: "pyodide/runtime-core.js",
1289
2255
  pythonSnippets: "generated-python-harness-snippets.js",
1290
2256
  javascriptWorker: "javascript-worker.js",
2257
+ javaWorker: "java-worker.js",
1291
2258
  typescriptCompiler: "vendor/typescript.js"
1292
2259
  });
1293
2260
  function isExplicitAssetPath(pathname) {
@@ -1321,6 +2288,7 @@ function resolveBrowserHarnessAssets(options = {}) {
1321
2288
  assetBaseUrl,
1322
2289
  assets.javascriptWorker ?? DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS.javascriptWorker
1323
2290
  ),
2291
+ javaWorker: resolveAssetPath(assetBaseUrl, assets.javaWorker ?? DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS.javaWorker),
1324
2292
  typescriptCompiler: resolveAssetPath(
1325
2293
  assetBaseUrl,
1326
2294
  assets.typescriptCompiler ?? DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS.typescriptCompiler
@@ -1334,6 +2302,7 @@ var BrowserHarnessRuntime = class {
1334
2302
  supportedLanguages = SUPPORTED_LANGUAGES;
1335
2303
  pythonWorkerClient;
1336
2304
  javaScriptWorkerClient;
2305
+ javaWorkerClient;
1337
2306
  clients;
1338
2307
  constructor(options = {}) {
1339
2308
  this.assets = resolveBrowserHarnessAssets(options);
@@ -1345,10 +2314,15 @@ var BrowserHarnessRuntime = class {
1345
2314
  workerUrl: this.assets.javascriptWorker,
1346
2315
  debug: options.debug
1347
2316
  });
2317
+ this.javaWorkerClient = new JavaWorkerClient({
2318
+ workerUrl: this.assets.javaWorker,
2319
+ debug: options.debug
2320
+ });
1348
2321
  this.clients = {
1349
2322
  python: createPythonRuntimeClient(this.pythonWorkerClient),
1350
2323
  javascript: createJavaScriptRuntimeClient("javascript", this.javaScriptWorkerClient),
1351
- typescript: createJavaScriptRuntimeClient("typescript", this.javaScriptWorkerClient)
2324
+ typescript: createJavaScriptRuntimeClient("typescript", this.javaScriptWorkerClient),
2325
+ java: createJavaRuntimeClient(this.javaWorkerClient)
1352
2326
  };
1353
2327
  }
1354
2328
  getClient(language) {
@@ -1372,11 +2346,16 @@ var BrowserHarnessRuntime = class {
1372
2346
  this.pythonWorkerClient.terminate();
1373
2347
  return;
1374
2348
  }
2349
+ if (language === "java") {
2350
+ this.javaWorkerClient.terminate();
2351
+ return;
2352
+ }
1375
2353
  this.javaScriptWorkerClient.terminate();
1376
2354
  }
1377
2355
  dispose() {
1378
2356
  this.pythonWorkerClient.terminate();
1379
2357
  this.javaScriptWorkerClient.terminate();
2358
+ this.javaWorkerClient.terminate();
1380
2359
  }
1381
2360
  };
1382
2361
  function createBrowserHarness(options = {}) {
@@ -1479,7 +2458,7 @@ def _serialize(obj, depth=0, node_refs=None):
1479
2458
  except TypeError:
1480
2459
  sorted_vals = [_serialize(x, depth + 1, node_refs) for x in obj]
1481
2460
  return {"__type__": "set", "values": sorted_vals}
1482
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
2461
+ elif isinstance(obj, TreeNode):
1483
2462
  obj_ref = id(obj)
1484
2463
  if obj_ref in node_refs:
1485
2464
  return {"__ref__": node_refs[obj_ref]}
@@ -1495,7 +2474,7 @@ def _serialize(obj, depth=0, node_refs=None):
1495
2474
  if hasattr(obj, 'right'):
1496
2475
  result["right"] = _serialize(obj.right, depth + 1, node_refs)
1497
2476
  return result
1498
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
2477
+ elif isinstance(obj, ListNode):
1499
2478
  obj_ref = id(obj)
1500
2479
  if obj_ref in node_refs:
1501
2480
  return {"__ref__": node_refs[obj_ref]}
@@ -1573,14 +2552,14 @@ def _serialize(obj, depth=0):
1573
2552
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
1574
2553
  except TypeError:
1575
2554
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
1576
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
2555
+ elif isinstance(obj, TreeNode):
1577
2556
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1578
2557
  if hasattr(obj, 'left'):
1579
2558
  result["left"] = _serialize(obj.left, depth + 1)
1580
2559
  if hasattr(obj, 'right'):
1581
2560
  result["right"] = _serialize(obj.right, depth + 1)
1582
2561
  return result
1583
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
2562
+ elif isinstance(obj, ListNode):
1584
2563
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1585
2564
  result["next"] = _serialize(obj.next, depth + 1)
1586
2565
  return result
@@ -1655,14 +2634,14 @@ def _serialize(obj, depth=0):
1655
2634
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
1656
2635
  except TypeError:
1657
2636
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
1658
- elif hasattr(obj, 'val') and (hasattr(obj, 'left') or hasattr(obj, 'right')):
2637
+ elif isinstance(obj, TreeNode):
1659
2638
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
1660
2639
  if hasattr(obj, 'left'):
1661
2640
  result["left"] = _serialize(obj.left, depth + 1)
1662
2641
  if hasattr(obj, 'right'):
1663
2642
  result["right"] = _serialize(obj.right, depth + 1)
1664
2643
  return result
1665
- elif hasattr(obj, 'val') and hasattr(obj, 'next'):
2644
+ elif isinstance(obj, ListNode):
1666
2645
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
1667
2646
  result["next"] = _serialize(obj.next, depth + 1)
1668
2647
  return result
@@ -1694,14 +2673,14 @@ def _serialize(obj, depth=0):
1694
2673
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
1695
2674
  except TypeError:
1696
2675
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
1697
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
2676
+ elif isinstance(obj, TreeNode):
1698
2677
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1699
2678
  if hasattr(obj, 'left'):
1700
2679
  result["left"] = _serialize(obj.left, depth + 1)
1701
2680
  if hasattr(obj, 'right'):
1702
2681
  result["right"] = _serialize(obj.right, depth + 1)
1703
2682
  return result
1704
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
2683
+ elif isinstance(obj, ListNode):
1705
2684
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1706
2685
  result["next"] = _serialize(obj.next, depth + 1)
1707
2686
  return result
@@ -1929,7 +2908,7 @@ def _serialize(obj, depth=0, node_refs=None):
1929
2908
  except TypeError:
1930
2909
  sorted_vals = [_serialize(x, depth + 1, node_refs) for x in obj]
1931
2910
  return {"__type__": "set", "values": sorted_vals}
1932
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
2911
+ elif isinstance(obj, TreeNode):
1933
2912
  obj_ref = id(obj)
1934
2913
  if obj_ref in node_refs:
1935
2914
  return {"__ref__": node_refs[obj_ref]}
@@ -1945,7 +2924,7 @@ def _serialize(obj, depth=0, node_refs=None):
1945
2924
  if hasattr(obj, 'right'):
1946
2925
  result["right"] = _serialize(obj.right, depth + 1, node_refs)
1947
2926
  return result
1948
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
2927
+ elif isinstance(obj, ListNode):
1949
2928
  obj_ref = id(obj)
1950
2929
  if obj_ref in node_refs:
1951
2930
  return {"__ref__": node_refs[obj_ref]}
@@ -2023,14 +3002,14 @@ def _serialize(obj, depth=0):
2023
3002
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
2024
3003
  except TypeError:
2025
3004
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
2026
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
3005
+ elif isinstance(obj, TreeNode):
2027
3006
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
2028
3007
  if hasattr(obj, 'left'):
2029
3008
  result["left"] = _serialize(obj.left, depth + 1)
2030
3009
  if hasattr(obj, 'right'):
2031
3010
  result["right"] = _serialize(obj.right, depth + 1)
2032
3011
  return result
2033
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
3012
+ elif isinstance(obj, ListNode):
2034
3013
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
2035
3014
  result["next"] = _serialize(obj.next, depth + 1)
2036
3015
  return result
@@ -2105,14 +3084,14 @@ def _serialize(obj, depth=0):
2105
3084
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
2106
3085
  except TypeError:
2107
3086
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
2108
- elif hasattr(obj, 'val') and (hasattr(obj, 'left') or hasattr(obj, 'right')):
3087
+ elif isinstance(obj, TreeNode):
2109
3088
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
2110
3089
  if hasattr(obj, 'left'):
2111
3090
  result["left"] = _serialize(obj.left, depth + 1)
2112
3091
  if hasattr(obj, 'right'):
2113
3092
  result["right"] = _serialize(obj.right, depth + 1)
2114
3093
  return result
2115
- elif hasattr(obj, 'val') and hasattr(obj, 'next'):
3094
+ elif isinstance(obj, ListNode):
2116
3095
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
2117
3096
  result["next"] = _serialize(obj.next, depth + 1)
2118
3097
  return result
@@ -2206,16 +3185,17 @@ function createConsoleProxy(output) {
2206
3185
  }
2207
3186
  function isLikelyTreeNodeValue(value) {
2208
3187
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
2209
- const hasValue = "val" in value || "value" in value;
2210
- const hasTreeLinks = "left" in value || "right" in value;
2211
- return hasValue && hasTreeLinks;
3188
+ const record = value;
3189
+ if (record.__type__ === "TreeNode") return true;
3190
+ const ctor = value.constructor;
3191
+ return ctor?.name === "TreeNode";
2212
3192
  }
2213
3193
  function isLikelyListNodeValue(value) {
2214
3194
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
2215
- const hasValue = "val" in value || "value" in value;
2216
- const hasTreeLinks = "left" in value || "right" in value;
2217
- const hasListLinks = "next" in value || "prev" in value;
2218
- return hasValue && hasListLinks && !hasTreeLinks;
3195
+ const record = value;
3196
+ if (record.__type__ === "ListNode") return true;
3197
+ const ctor = value.constructor;
3198
+ return ctor?.name === "ListNode";
2219
3199
  }
2220
3200
  function getCustomClassName(value) {
2221
3201
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
@@ -2270,22 +3250,25 @@ function serializeValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(),
2270
3250
  const nodePrefix = isTree ? "tree" : "list";
2271
3251
  const nodeId = `${nodePrefix}-${nodeRefState.nextId++}`;
2272
3252
  nodeRefState.ids.set(objectValue, nodeId);
2273
- if (isTree) {
2274
- return {
2275
- __type__: "TreeNode",
2276
- __id__: nodeId,
2277
- val: serializeValue(nodeValue.val ?? nodeValue.value ?? null, depth + 1, seen, nodeRefState),
2278
- left: serializeValue(nodeValue.left ?? null, depth + 1, seen, nodeRefState),
2279
- right: serializeValue(nodeValue.right ?? null, depth + 1, seen, nodeRefState)
2280
- };
2281
- }
2282
- return {
3253
+ const out2 = isTree ? {
3254
+ __type__: "TreeNode",
3255
+ __id__: nodeId,
3256
+ val: serializeValue(nodeValue.val ?? nodeValue.value ?? null, depth + 1, seen, nodeRefState),
3257
+ left: serializeValue(nodeValue.left ?? null, depth + 1, seen, nodeRefState),
3258
+ right: serializeValue(nodeValue.right ?? null, depth + 1, seen, nodeRefState)
3259
+ } : {
2283
3260
  __type__: "ListNode",
2284
3261
  __id__: nodeId,
2285
3262
  val: serializeValue(nodeValue.val ?? nodeValue.value ?? null, depth + 1, seen, nodeRefState),
2286
3263
  next: serializeValue(nodeValue.next ?? null, depth + 1, seen, nodeRefState),
2287
3264
  ..."prev" in nodeValue ? { prev: serializeValue(nodeValue.prev ?? null, depth + 1, seen, nodeRefState) } : {}
2288
3265
  };
3266
+ const skipped = isTree ? /* @__PURE__ */ new Set(["__id__", "__type__", "__class__", "val", "value", "left", "right"]) : /* @__PURE__ */ new Set(["__id__", "__type__", "__class__", "val", "value", "next", "prev"]);
3267
+ for (const [k, v] of Object.entries(nodeValue)) {
3268
+ if (skipped.has(k)) continue;
3269
+ out2[k] = serializeValue(v, depth + 1, seen, nodeRefState);
3270
+ }
3271
+ return out2;
2289
3272
  }
2290
3273
  const customClassName = getCustomClassName(value);
2291
3274
  if (customClassName) {
@@ -2449,21 +3432,31 @@ function materializeTreeInput(value) {
2449
3432
  }
2450
3433
  const record = value;
2451
3434
  if (isLikelyTreeNodeValue(record)) {
2452
- return {
3435
+ const node = {
2453
3436
  val: record.val ?? record.value ?? null,
2454
3437
  value: record.val ?? record.value ?? null,
2455
3438
  left: materializeTreeInput(record.left ?? null),
2456
3439
  right: materializeTreeInput(record.right ?? null)
2457
3440
  };
3441
+ for (const [key, nested] of Object.entries(record)) {
3442
+ if (key === "__id__" || key === "__type__" || key === "val" || key === "value" || key === "left" || key === "right") continue;
3443
+ node[key] = materializeTreeInput(nested);
3444
+ }
3445
+ return node;
2458
3446
  }
2459
3447
  const taggedRecord = value;
2460
3448
  if (taggedRecord.__type__ === "TreeNode") {
2461
- return {
3449
+ const node = {
2462
3450
  val: taggedRecord.val ?? taggedRecord.value ?? null,
2463
3451
  value: taggedRecord.val ?? taggedRecord.value ?? null,
2464
3452
  left: materializeTreeInput(taggedRecord.left ?? null),
2465
3453
  right: materializeTreeInput(taggedRecord.right ?? null)
2466
3454
  };
3455
+ for (const [key, nested] of Object.entries(taggedRecord)) {
3456
+ if (key === "__id__" || key === "__type__" || key === "val" || key === "value" || key === "left" || key === "right") continue;
3457
+ node[key] = materializeTreeInput(nested);
3458
+ }
3459
+ return node;
2467
3460
  }
2468
3461
  return value;
2469
3462
  }
@@ -2507,6 +3500,10 @@ function materializeListInput(value, refs = /* @__PURE__ */ new Map(), materiali
2507
3500
  refs.set(taggedRecord.__id__, node);
2508
3501
  }
2509
3502
  node.next = materializeListInput(taggedRecord.next ?? null, refs, materialized);
3503
+ for (const [key, nested] of Object.entries(taggedRecord)) {
3504
+ if (key === "__id__" || key === "__type__" || key === "__class__" || key === "val" || key === "value" || key === "next") continue;
3505
+ node[key] = materializeListInput(nested, refs, materialized);
3506
+ }
2510
3507
  return node;
2511
3508
  }
2512
3509
  return value;
@@ -2871,9 +3868,13 @@ async function executeTypeScriptCode(code, functionName, inputs, executionStyle
2871
3868
  TEMPLATE_PYTHON_TRACE_SERIALIZE_FUNCTION,
2872
3869
  TYPESCRIPT_RUNTIME_DECLARATIONS,
2873
3870
  adaptJavaScriptTraceExecutionResult,
3871
+ adaptJavaSpikeTraceExecutionResult,
3872
+ adaptJavaTraceExecutionResult,
2874
3873
  adaptPythonTraceExecutionResult,
2875
3874
  adaptTraceExecutionResult,
2876
3875
  assertRuntimeRequestSupported,
3876
+ buildJavaExecutionResult,
3877
+ buildJavaSpikeExecutionResult,
2877
3878
  createBrowserHarness,
2878
3879
  executeJavaScriptCode,
2879
3880
  executeJavaScriptWithTracing,
@@ -2885,6 +3886,8 @@ async function executeTypeScriptCode(code, functionName, inputs, executionStyle
2885
3886
  getSupportedLanguageProfiles,
2886
3887
  identifyConversions,
2887
3888
  isLanguageSupported,
3889
+ normalizeJavaSpikeTraceContract,
3890
+ normalizeJavaTraceContract,
2888
3891
  normalizeRuntimeTraceContract,
2889
3892
  resolveBrowserHarnessAssets,
2890
3893
  stableStringifyRuntimeTraceContract,