@tracecode/harness 0.6.2 → 0.6.6

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.
package/dist/browser.js CHANGED
@@ -1189,6 +1189,16 @@ function parseScalar(raw) {
1189
1189
  }
1190
1190
  return raw;
1191
1191
  }
1192
+ function normalizeJavaSerializedResult(output) {
1193
+ if (typeof output !== "string") {
1194
+ return output;
1195
+ }
1196
+ try {
1197
+ return JSON.parse(output);
1198
+ } catch {
1199
+ return output;
1200
+ }
1201
+ }
1192
1202
  function parseKeyValuePairs(fragment) {
1193
1203
  const variables = {};
1194
1204
  const matches = Array.from(fragment.matchAll(/\b([A-Za-z_][A-Za-z0-9_.]*)=/g));
@@ -1369,10 +1379,29 @@ function parseAccessEvent(payload) {
1369
1379
  pathDepth: 1
1370
1380
  }];
1371
1381
  }
1382
+ const indexedMutatingCall = payload.match(/^mutate-indexed ([A-Za-z_][A-Za-z0-9_]*)\[(\d+)\] method=([A-Za-z_][A-Za-z0-9_]*)$/);
1383
+ if (indexedMutatingCall) {
1384
+ return [{
1385
+ variable: indexedMutatingCall[1],
1386
+ kind: "mutating-call",
1387
+ indices: [Number.parseInt(indexedMutatingCall[2], 10)],
1388
+ method: indexedMutatingCall[3],
1389
+ pathDepth: 1
1390
+ }];
1391
+ }
1392
+ const keyedCall = payload.match(/^keyed-call ([A-Za-z_][A-Za-z0-9_]*) method=([A-Za-z_][A-Za-z0-9_]*)(?:\s+.*)?$/);
1393
+ if (keyedCall) {
1394
+ return [{
1395
+ variable: keyedCall[1],
1396
+ kind: "mutating-call",
1397
+ method: keyedCall[2],
1398
+ pathDepth: 1
1399
+ }];
1400
+ }
1372
1401
  return void 0;
1373
1402
  }
1374
1403
  function parseStructureState(payload) {
1375
- const match = payload.match(/^state (linked-list|tree) ([A-Za-z_][A-Za-z0-9_]*)=(.+)$/);
1404
+ const match = payload.match(/^state (linked-list|tree|graph-adjacency) ([A-Za-z_][A-Za-z0-9_]*)=(.+)$/);
1376
1405
  if (!match) return null;
1377
1406
  return {
1378
1407
  structure: match[1],
@@ -1388,6 +1417,22 @@ function parseObjectState(payload) {
1388
1417
  visualization: JSON.parse(match[2])
1389
1418
  };
1390
1419
  }
1420
+ function parseMapState(payload) {
1421
+ const match = payload.match(/^map-state ([A-Za-z_][A-Za-z0-9_]*)=(.+)$/);
1422
+ if (!match) return null;
1423
+ return {
1424
+ variable: match[1],
1425
+ visualization: JSON.parse(match[2])
1426
+ };
1427
+ }
1428
+ function parseSetState(payload) {
1429
+ const match = payload.match(/^set-state ([A-Za-z_][A-Za-z0-9_]*)=(.+)$/);
1430
+ if (!match) return null;
1431
+ return {
1432
+ variable: match[1],
1433
+ visualization: JSON.parse(match[2])
1434
+ };
1435
+ }
1391
1436
  function parseObjectFieldEvent(payload) {
1392
1437
  const match = payload.match(/^(access|write) ([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)=(.+)$/);
1393
1438
  if (!match) return null;
@@ -1397,6 +1442,9 @@ function parseObjectFieldEvent(payload) {
1397
1442
  value: parseScalar(match[4])
1398
1443
  };
1399
1444
  }
1445
+ function isArrayLengthAccessEvent(payload) {
1446
+ return /^access [A-Za-z_][A-Za-z0-9_]*\.length=\d+$/.test(payload);
1447
+ }
1400
1448
  function buildFieldVisualization(event) {
1401
1449
  return {
1402
1450
  objectKinds: {
@@ -1476,12 +1524,13 @@ function filterStructuredVariables(variables) {
1476
1524
  }
1477
1525
  return Object.fromEntries(entries);
1478
1526
  }
1479
- function appendJavaTraceStep(trace, step, pendingAccesses) {
1527
+ function appendJavaTraceStep(trace, step, pendingAccesses, options = {}) {
1480
1528
  const nextStep = pendingAccesses.length > 0 ? { ...step, accesses: [...pendingAccesses] } : step;
1481
1529
  pendingAccesses.length = 0;
1482
- if (!maybeMergeConsecutiveLineStep(trace, nextStep)) {
1483
- trace.push(nextStep);
1530
+ if (options.allowMerge !== false && maybeMergeConsecutiveLineStep(trace, nextStep)) {
1531
+ return;
1484
1532
  }
1533
+ trace.push(nextStep);
1485
1534
  }
1486
1535
  function mergeIntoPreviousMatchingLineStep(trace, line, currentFunction, currentCallStack, patch) {
1487
1536
  const candidate = trace.at(-1);
@@ -1515,11 +1564,14 @@ function eventsToRawTrace(events, sourceText) {
1515
1564
  const stack = [];
1516
1565
  const pendingAccesses = [];
1517
1566
  let currentFunction = "<module>";
1567
+ let previousRawLine = null;
1518
1568
  const lineRemap = buildLineRemap(sourceText);
1519
1569
  const declarationLines = buildMethodDeclarationLineSet(sourceText);
1520
1570
  for (const rawEvent of events) {
1521
1571
  if (rawEvent === "clear" || rawEvent === "reset") continue;
1522
1572
  const metadata = extractLineMetadata(rawEvent);
1573
+ const previousEventRawLine = previousRawLine;
1574
+ previousRawLine = metadata.line;
1523
1575
  const line = lineRemap?.get(metadata.line) ?? metadata.line;
1524
1576
  const payload = metadata.payload;
1525
1577
  const isDeclarationLine = declarationLines?.has(line) === true;
@@ -1527,28 +1579,31 @@ function eventsToRawTrace(events, sourceText) {
1527
1579
  const match = payload.match(/^call\s+(\S+)(?:\s+(.*))?$/);
1528
1580
  const functionName = match?.[1] ?? currentFunction;
1529
1581
  const argsFragment = match?.[2] ?? "";
1530
- Object.assign(variables, parseKeyValuePairs(argsFragment));
1582
+ const args = parseKeyValuePairs(argsFragment);
1583
+ Object.assign(variables, args);
1531
1584
  currentFunction = functionName || currentFunction;
1532
- stack.push({ function: currentFunction, line });
1585
+ stack.push({ function: currentFunction, line, args });
1533
1586
  appendJavaTraceStep(trace, {
1534
1587
  line,
1535
1588
  event: "call",
1536
1589
  function: currentFunction,
1537
1590
  variables: { ...variables },
1538
- callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} }))
1591
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } }))
1539
1592
  }, pendingAccesses);
1540
1593
  continue;
1541
1594
  }
1542
1595
  if (payload.startsWith("return ")) {
1543
- const match = payload.match(/^return\s+(\S+)$/);
1596
+ const match = payload.match(/^return\s+(\S+)(?:\s+value=(.*))?$/);
1544
1597
  const functionName = match?.[1] ?? currentFunction;
1598
+ const returnValue = match?.[2] !== void 0 ? parseScalar(match[2].trim()) : void 0;
1545
1599
  const returnVariables = functionName === "<module>" ? { ...variables } : filterStructuredVariables(variables) ?? {};
1546
1600
  appendJavaTraceStep(trace, {
1547
1601
  line,
1548
1602
  event: "return",
1549
1603
  function: functionName || currentFunction,
1550
1604
  variables: returnVariables,
1551
- callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} }))
1605
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })),
1606
+ ...returnValue !== void 0 ? { returnValue } : {}
1552
1607
  }, pendingAccesses);
1553
1608
  stack.pop();
1554
1609
  currentFunction = stack[stack.length - 1]?.function ?? "<module>";
@@ -1563,8 +1618,8 @@ function eventsToRawTrace(events, sourceText) {
1563
1618
  event: "line",
1564
1619
  function: currentFunction,
1565
1620
  variables: { ...variables },
1566
- ...stack.length > 0 ? { callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })) } : {}
1567
- }, pendingAccesses);
1621
+ ...stack.length > 0 ? { callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })) } : {}
1622
+ }, pendingAccesses, { allowMerge: previousEventRawLine !== metadata.line });
1568
1623
  continue;
1569
1624
  }
1570
1625
  const structureState = parseStructureState(payload);
@@ -1576,7 +1631,7 @@ function eventsToRawTrace(events, sourceText) {
1576
1631
  event: "line",
1577
1632
  function: currentFunction,
1578
1633
  variables: { ...variables },
1579
- callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })),
1634
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })),
1580
1635
  visualization: {
1581
1636
  objectKinds: { ...objectKinds }
1582
1637
  }
@@ -1591,7 +1646,7 @@ function eventsToRawTrace(events, sourceText) {
1591
1646
  event: "line",
1592
1647
  function: currentFunction,
1593
1648
  variables: { ...variables },
1594
- callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })),
1649
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })),
1595
1650
  visualization: {
1596
1651
  objectKinds: { [objectState.variable]: "object" },
1597
1652
  hashMaps: [objectState.visualization]
@@ -1599,10 +1654,56 @@ function eventsToRawTrace(events, sourceText) {
1599
1654
  }, pendingAccesses);
1600
1655
  continue;
1601
1656
  }
1657
+ const mapState = parseMapState(payload);
1658
+ if (mapState) {
1659
+ const entries = mapState.visualization.entries.map((entry) => [entry.key, entry.value]);
1660
+ variables[mapState.variable] = { __type__: "map", entries };
1661
+ appendJavaTraceStep(trace, {
1662
+ line,
1663
+ event: "line",
1664
+ function: currentFunction,
1665
+ variables: { ...variables },
1666
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })),
1667
+ visualization: {
1668
+ objectKinds: { [mapState.variable]: "map" },
1669
+ hashMaps: [mapState.visualization]
1670
+ }
1671
+ }, pendingAccesses);
1672
+ continue;
1673
+ }
1674
+ const setState = parseSetState(payload);
1675
+ if (setState) {
1676
+ const values = setState.visualization.entries.map((entry) => entry.key);
1677
+ variables[setState.variable] = { __type__: "set", values };
1678
+ appendJavaTraceStep(trace, {
1679
+ line,
1680
+ event: "line",
1681
+ function: currentFunction,
1682
+ variables: { ...variables },
1683
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })),
1684
+ visualization: {
1685
+ objectKinds: { [setState.variable]: "set" },
1686
+ hashMaps: [setState.visualization]
1687
+ }
1688
+ }, pendingAccesses);
1689
+ continue;
1690
+ }
1691
+ if (isArrayLengthAccessEvent(payload)) {
1692
+ continue;
1693
+ }
1694
+ const accesses = parseAccessEvent(payload);
1695
+ if (accesses) {
1696
+ const currentCallStack = stack.length > 0 ? stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })) : void 0;
1697
+ if (mergeAccessesIntoPreviousMatchingLineStep(trace, line, currentFunction, currentCallStack, accesses)) {
1698
+ continue;
1699
+ }
1700
+ pendingAccesses.push(...accesses);
1701
+ continue;
1702
+ }
1602
1703
  const objectField = parseObjectFieldEvent(payload);
1603
1704
  if (objectField) {
1604
1705
  variables[objectField.variable] = { __ref__: `${objectField.variable}-object` };
1605
- const currentCallStack = stack.length > 0 ? stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })) : void 0;
1706
+ const currentCallStack = stack.length > 0 ? stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })) : void 0;
1606
1707
  if (mergeIntoPreviousMatchingLineStep(trace, line, currentFunction, currentCallStack, {
1607
1708
  variables: { ...variables },
1608
1709
  accesses: void 0,
@@ -1615,27 +1716,18 @@ function eventsToRawTrace(events, sourceText) {
1615
1716
  event: "line",
1616
1717
  function: currentFunction,
1617
1718
  variables: { ...variables },
1618
- callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })),
1719
+ callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })),
1619
1720
  visualization: buildFieldVisualization(objectField)
1620
1721
  }, pendingAccesses);
1621
1722
  continue;
1622
1723
  }
1623
1724
  Object.assign(variables, parseKeyValuePairs(payload));
1624
- const accesses = parseAccessEvent(payload);
1625
- if (accesses) {
1626
- const currentCallStack = stack.length > 0 ? stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })) : void 0;
1627
- if (mergeAccessesIntoPreviousMatchingLineStep(trace, line, currentFunction, currentCallStack, accesses)) {
1628
- continue;
1629
- }
1630
- pendingAccesses.push(...accesses);
1631
- continue;
1632
- }
1633
1725
  appendJavaTraceStep(trace, {
1634
1726
  line,
1635
1727
  event: "line",
1636
1728
  function: currentFunction,
1637
1729
  variables: { ...variables },
1638
- ...stack.length > 0 ? { callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: {} })) } : {}
1730
+ ...stack.length > 0 ? { callStack: stack.map((frame) => ({ function: frame.function, line: frame.line, args: { ...frame.args } })) } : {}
1639
1731
  }, pendingAccesses);
1640
1732
  }
1641
1733
  if (pendingAccesses.length > 0 && trace.length > 0) {
@@ -1644,11 +1736,11 @@ function eventsToRawTrace(events, sourceText) {
1644
1736
  }
1645
1737
  return trace;
1646
1738
  }
1647
- function buildJavaExecutionResult(output, events, executionTimeMs = 0, traceLimitExceeded, timeoutReason, maxTraceSteps, sourceText) {
1739
+ function buildJavaExecutionResult(output, events, executionTimeMs = 0, traceLimitExceeded, timeoutReason, maxTraceSteps, sourceText, options = {}) {
1648
1740
  const trace = eventsToRawTrace(events, sourceText);
1649
1741
  return {
1650
1742
  success: true,
1651
- output,
1743
+ output: options.outputIsSerialized === false ? output : normalizeJavaSerializedResult(output),
1652
1744
  trace,
1653
1745
  executionTimeMs,
1654
1746
  consoleOutput: [],
@@ -1706,7 +1798,8 @@ var JavaRuntimeClient = class {
1706
1798
  rawResult.traceLimitExceeded,
1707
1799
  rawResult.timeoutReason,
1708
1800
  void 0,
1709
- rawResult.sourceText
1801
+ rawResult.sourceText,
1802
+ { outputIsSerialized: false }
1710
1803
  )
1711
1804
  );
1712
1805
  return {