@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/CHANGELOG.md +23 -0
- package/dist/browser.cjs +121 -28
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +121 -28
- package/dist/browser.js.map +1 -1
- package/dist/cli.cjs +4 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/core.cjs +121 -27
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +5 -2
- package/dist/core.d.ts +5 -2
- package/dist/core.js +120 -27
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +124 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +123 -28
- package/dist/index.js.map +1 -1
- package/dist/python.cjs +1 -0
- package/dist/python.cjs.map +1 -1
- package/dist/python.js +1 -0
- package/dist/python.js.map +1 -1
- package/package.json +5 -3
- package/workers/java/java-source-augmentations.cjs +242 -0
- package/workers/java/java-worker.js +856 -34
- package/workers/java/src/spike/user/TraceHooks.java +619 -0
- package/workers/python/runtime-core.js +78 -16
- package/workers/vendor/java-browser-spike-helper.jar +0 -0
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 (
|
|
1483
|
-
|
|
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
|
-
|
|
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 {
|