@tracecode/harness 0.4.0 → 0.5.1
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 +15 -0
- package/LICENSE +67 -80
- package/README.md +2 -1
- package/dist/browser.cjs +16 -4
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +16 -4
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +0 -0
- package/dist/core.cjs +16 -4
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +9 -6
- package/dist/core.d.ts +9 -6
- package/dist/core.js +16 -4
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +354 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +354 -44
- package/dist/index.js.map +1 -1
- package/dist/internal/browser.d.cts +1 -1
- package/dist/internal/browser.d.ts +1 -1
- package/dist/javascript.cjs +262 -26
- package/dist/javascript.cjs.map +1 -1
- package/dist/javascript.d.cts +4 -4
- package/dist/javascript.d.ts +4 -4
- package/dist/javascript.js +262 -26
- package/dist/javascript.js.map +1 -1
- package/dist/python.cjs +76 -14
- package/dist/python.cjs.map +1 -1
- package/dist/python.d.cts +8 -8
- package/dist/python.d.ts +8 -8
- package/dist/python.js +76 -14
- package/dist/python.js.map +1 -1
- package/dist/{runtime-types-Dvgn07z9.d.cts → runtime-types--lBQ6rYu.d.cts} +1 -1
- package/dist/{runtime-types-C7d1LFbx.d.ts → runtime-types-DtaaAhHL.d.ts} +1 -1
- package/dist/{types-Bzr1Ohcf.d.cts → types-DwIYM3Ku.d.cts} +5 -2
- package/dist/{types-Bzr1Ohcf.d.ts → types-DwIYM3Ku.d.ts} +5 -2
- package/package.json +13 -11
- package/workers/javascript/javascript-worker.js +455 -31
- package/workers/python/generated-python-harness-snippets.js +1 -1
- package/workers/python/pyodide-worker.js +31 -0
- package/workers/python/runtime-core.js +235 -8
package/dist/index.cjs
CHANGED
|
@@ -63,7 +63,7 @@ __export(src_exports, {
|
|
|
63
63
|
module.exports = __toCommonJS(src_exports);
|
|
64
64
|
|
|
65
65
|
// packages/harness-core/src/trace-contract.ts
|
|
66
|
-
var RUNTIME_TRACE_CONTRACT_SCHEMA_VERSION = "2026-03-
|
|
66
|
+
var RUNTIME_TRACE_CONTRACT_SCHEMA_VERSION = "2026-03-13";
|
|
67
67
|
var TRACE_EVENTS = /* @__PURE__ */ new Set([
|
|
68
68
|
"line",
|
|
69
69
|
"call",
|
|
@@ -106,13 +106,13 @@ function normalizeFunctionName(value) {
|
|
|
106
106
|
return "<module>";
|
|
107
107
|
}
|
|
108
108
|
function normalizeKind(value) {
|
|
109
|
-
if (value === "map" || value === "set" || value === "hashmap") {
|
|
109
|
+
if (value === "map" || value === "set" || value === "hashmap" || value === "object") {
|
|
110
110
|
return value;
|
|
111
111
|
}
|
|
112
112
|
return "hashmap";
|
|
113
113
|
}
|
|
114
114
|
function normalizeObjectKind(value) {
|
|
115
|
-
if (value === "hashmap" || value === "map" || value === "set" || value === "tree" || value === "linked-list" || value === "graph-adjacency") {
|
|
115
|
+
if (value === "hashmap" || value === "object" || value === "map" || value === "set" || value === "tree" || value === "linked-list" || value === "graph-adjacency") {
|
|
116
116
|
return value;
|
|
117
117
|
}
|
|
118
118
|
return null;
|
|
@@ -190,6 +190,14 @@ function normalizeRecord(value) {
|
|
|
190
190
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
191
191
|
return normalizeUnknown(value);
|
|
192
192
|
}
|
|
193
|
+
function normalizeVariableSources(value) {
|
|
194
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
195
|
+
const entries = Object.entries(value).filter(
|
|
196
|
+
([name, source]) => typeof name === "string" && name.length > 0 && (source === "user" || source === "user-input" || source === "harness-prelude")
|
|
197
|
+
).sort((a, b) => a[0].localeCompare(b[0]));
|
|
198
|
+
if (entries.length === 0) return void 0;
|
|
199
|
+
return Object.fromEntries(entries);
|
|
200
|
+
}
|
|
193
201
|
function normalizeCallStackFrame(frame) {
|
|
194
202
|
return {
|
|
195
203
|
function: normalizeFunctionName(frame?.function),
|
|
@@ -207,7 +215,9 @@ function normalizeVisualizationPayload(payload) {
|
|
|
207
215
|
...item?.highlight ? { highlight: true } : {}
|
|
208
216
|
})) : [],
|
|
209
217
|
...entry?.highlightedKey !== void 0 ? { highlightedKey: normalizeUnknown(entry.highlightedKey) } : {},
|
|
210
|
-
...entry?.deletedKey !== void 0 ? { deletedKey: normalizeUnknown(entry.deletedKey) } : {}
|
|
218
|
+
...entry?.deletedKey !== void 0 ? { deletedKey: normalizeUnknown(entry.deletedKey) } : {},
|
|
219
|
+
...typeof entry?.objectClassName === "string" && entry.objectClassName.length > 0 ? { objectClassName: entry.objectClassName } : {},
|
|
220
|
+
...typeof entry?.objectId === "string" && entry.objectId.length > 0 ? { objectId: entry.objectId } : {}
|
|
211
221
|
})).sort((a, b) => `${a.name}:${a.kind}`.localeCompare(`${b.name}:${b.kind}`)) : [];
|
|
212
222
|
const objectKinds = payload?.objectKinds && typeof payload.objectKinds === "object" ? Object.fromEntries(
|
|
213
223
|
Object.entries(payload.objectKinds).filter(([name]) => typeof name === "string" && name.length > 0).map(([name, kind]) => [name, normalizeObjectKind(kind)]).filter((entry) => entry[1] !== null).sort((a, b) => a[0].localeCompare(b[0]))
|
|
@@ -224,11 +234,13 @@ function normalizeTraceStep(step) {
|
|
|
224
234
|
const normalizedStdoutCount = normalizeOutputLineCount(step?.stdoutLineCount);
|
|
225
235
|
const normalizedVisualization = normalizeVisualizationPayload(step?.visualization);
|
|
226
236
|
const normalizedAccesses = normalizeAccesses(step?.accesses);
|
|
237
|
+
const normalizedVariableSources = normalizeVariableSources(step?.variableSources);
|
|
227
238
|
return {
|
|
228
239
|
event: normalizeEvent(step?.event),
|
|
229
240
|
line: normalizeLineNumber(step?.line, 1),
|
|
230
241
|
function: normalizeFunctionName(step?.function),
|
|
231
242
|
variables: normalizeRecord(step?.variables),
|
|
243
|
+
...normalizedVariableSources ? { variableSources: normalizedVariableSources } : {},
|
|
232
244
|
...Array.isArray(step?.callStack) && step.callStack.length > 0 ? { callStack: step.callStack.map(normalizeCallStackFrame) } : {},
|
|
233
245
|
...normalizedAccesses ? { accesses: normalizedAccesses } : {},
|
|
234
246
|
...step?.returnValue !== void 0 ? { returnValue: normalizeUnknown(step.returnValue) } : {},
|
|
@@ -1439,6 +1451,7 @@ var PYTHON_TRACE_SERIALIZE_FUNCTION = `
|
|
|
1439
1451
|
# Sentinel to mark skipped values (functions, etc.) - distinct from None
|
|
1440
1452
|
_SKIP_SENTINEL = "__TRACECODE_SKIP__"
|
|
1441
1453
|
_MAX_SERIALIZE_DEPTH = 48
|
|
1454
|
+
_MAX_OBJECT_FIELDS = 32
|
|
1442
1455
|
|
|
1443
1456
|
def _serialize(obj, depth=0, node_refs=None):
|
|
1444
1457
|
if node_refs is None:
|
|
@@ -1466,7 +1479,7 @@ def _serialize(obj, depth=0, node_refs=None):
|
|
|
1466
1479
|
except TypeError:
|
|
1467
1480
|
sorted_vals = [_serialize(x, depth + 1, node_refs) for x in obj]
|
|
1468
1481
|
return {"__type__": "set", "values": sorted_vals}
|
|
1469
|
-
elif (
|
|
1482
|
+
elif isinstance(obj, TreeNode):
|
|
1470
1483
|
obj_ref = id(obj)
|
|
1471
1484
|
if obj_ref in node_refs:
|
|
1472
1485
|
return {"__ref__": node_refs[obj_ref]}
|
|
@@ -1482,7 +1495,7 @@ def _serialize(obj, depth=0, node_refs=None):
|
|
|
1482
1495
|
if hasattr(obj, 'right'):
|
|
1483
1496
|
result["right"] = _serialize(obj.right, depth + 1, node_refs)
|
|
1484
1497
|
return result
|
|
1485
|
-
elif (
|
|
1498
|
+
elif isinstance(obj, ListNode):
|
|
1486
1499
|
obj_ref = id(obj)
|
|
1487
1500
|
if obj_ref in node_refs:
|
|
1488
1501
|
return {"__ref__": node_refs[obj_ref]}
|
|
@@ -1495,6 +1508,36 @@ def _serialize(obj, depth=0, node_refs=None):
|
|
|
1495
1508
|
}
|
|
1496
1509
|
result["next"] = _serialize(obj.next, depth + 1, node_refs)
|
|
1497
1510
|
return result
|
|
1511
|
+
elif hasattr(obj, '__dict__'):
|
|
1512
|
+
obj_ref = id(obj)
|
|
1513
|
+
if obj_ref in node_refs:
|
|
1514
|
+
return {"__ref__": node_refs[obj_ref]}
|
|
1515
|
+
node_id = f"object-{obj_ref}"
|
|
1516
|
+
node_refs[obj_ref] = node_id
|
|
1517
|
+
class_name = getattr(getattr(obj, '__class__', None), '__name__', 'object')
|
|
1518
|
+
result = {
|
|
1519
|
+
"__type__": "object",
|
|
1520
|
+
"__class__": class_name,
|
|
1521
|
+
"__id__": node_id,
|
|
1522
|
+
}
|
|
1523
|
+
try:
|
|
1524
|
+
raw_fields = getattr(obj, '__dict__', None)
|
|
1525
|
+
except Exception:
|
|
1526
|
+
raw_fields = None
|
|
1527
|
+
if isinstance(raw_fields, dict):
|
|
1528
|
+
added = 0
|
|
1529
|
+
for key, value in raw_fields.items():
|
|
1530
|
+
key_str = str(key)
|
|
1531
|
+
if key_str.startswith('_'):
|
|
1532
|
+
continue
|
|
1533
|
+
if callable(value):
|
|
1534
|
+
continue
|
|
1535
|
+
result[key_str] = _serialize(value, depth + 1, node_refs)
|
|
1536
|
+
added += 1
|
|
1537
|
+
if added >= _MAX_OBJECT_FIELDS:
|
|
1538
|
+
result["__truncated__"] = True
|
|
1539
|
+
break
|
|
1540
|
+
return result
|
|
1498
1541
|
elif callable(obj):
|
|
1499
1542
|
# Skip functions entirely - return sentinel
|
|
1500
1543
|
return _SKIP_SENTINEL
|
|
@@ -1530,14 +1573,14 @@ def _serialize(obj, depth=0):
|
|
|
1530
1573
|
return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
|
|
1531
1574
|
except TypeError:
|
|
1532
1575
|
return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
|
|
1533
|
-
elif (
|
|
1576
|
+
elif isinstance(obj, TreeNode):
|
|
1534
1577
|
result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
|
|
1535
1578
|
if hasattr(obj, 'left'):
|
|
1536
1579
|
result["left"] = _serialize(obj.left, depth + 1)
|
|
1537
1580
|
if hasattr(obj, 'right'):
|
|
1538
1581
|
result["right"] = _serialize(obj.right, depth + 1)
|
|
1539
1582
|
return result
|
|
1540
|
-
elif (
|
|
1583
|
+
elif isinstance(obj, ListNode):
|
|
1541
1584
|
result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
|
|
1542
1585
|
result["next"] = _serialize(obj.next, depth + 1)
|
|
1543
1586
|
return result
|
|
@@ -1612,14 +1655,14 @@ def _serialize(obj, depth=0):
|
|
|
1612
1655
|
return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
|
|
1613
1656
|
except TypeError:
|
|
1614
1657
|
return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
|
|
1615
|
-
elif
|
|
1658
|
+
elif isinstance(obj, TreeNode):
|
|
1616
1659
|
result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
|
|
1617
1660
|
if hasattr(obj, 'left'):
|
|
1618
1661
|
result["left"] = _serialize(obj.left, depth + 1)
|
|
1619
1662
|
if hasattr(obj, 'right'):
|
|
1620
1663
|
result["right"] = _serialize(obj.right, depth + 1)
|
|
1621
1664
|
return result
|
|
1622
|
-
elif
|
|
1665
|
+
elif isinstance(obj, ListNode):
|
|
1623
1666
|
result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
|
|
1624
1667
|
result["next"] = _serialize(obj.next, depth + 1)
|
|
1625
1668
|
return result
|
|
@@ -1651,14 +1694,14 @@ def _serialize(obj, depth=0):
|
|
|
1651
1694
|
return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
|
|
1652
1695
|
except TypeError:
|
|
1653
1696
|
return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
|
|
1654
|
-
elif (
|
|
1697
|
+
elif isinstance(obj, TreeNode):
|
|
1655
1698
|
result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
|
|
1656
1699
|
if hasattr(obj, 'left'):
|
|
1657
1700
|
result["left"] = _serialize(obj.left, depth + 1)
|
|
1658
1701
|
if hasattr(obj, 'right'):
|
|
1659
1702
|
result["right"] = _serialize(obj.right, depth + 1)
|
|
1660
1703
|
return result
|
|
1661
|
-
elif (
|
|
1704
|
+
elif isinstance(obj, ListNode):
|
|
1662
1705
|
result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
|
|
1663
1706
|
result["next"] = _serialize(obj.next, depth + 1)
|
|
1664
1707
|
return result
|
|
@@ -1858,6 +1901,7 @@ var TEMPLATE_PYTHON_TRACE_SERIALIZE_FUNCTION = `
|
|
|
1858
1901
|
# Sentinel to mark skipped values (functions, etc.) - distinct from None
|
|
1859
1902
|
_SKIP_SENTINEL = "__TRACECODE_SKIP__"
|
|
1860
1903
|
_MAX_SERIALIZE_DEPTH = 48
|
|
1904
|
+
_MAX_OBJECT_FIELDS = 32
|
|
1861
1905
|
|
|
1862
1906
|
def _serialize(obj, depth=0, node_refs=None):
|
|
1863
1907
|
if node_refs is None:
|
|
@@ -1885,7 +1929,7 @@ def _serialize(obj, depth=0, node_refs=None):
|
|
|
1885
1929
|
except TypeError:
|
|
1886
1930
|
sorted_vals = [_serialize(x, depth + 1, node_refs) for x in obj]
|
|
1887
1931
|
return {"__type__": "set", "values": sorted_vals}
|
|
1888
|
-
elif (
|
|
1932
|
+
elif isinstance(obj, TreeNode):
|
|
1889
1933
|
obj_ref = id(obj)
|
|
1890
1934
|
if obj_ref in node_refs:
|
|
1891
1935
|
return {"__ref__": node_refs[obj_ref]}
|
|
@@ -1901,7 +1945,7 @@ def _serialize(obj, depth=0, node_refs=None):
|
|
|
1901
1945
|
if hasattr(obj, 'right'):
|
|
1902
1946
|
result["right"] = _serialize(obj.right, depth + 1, node_refs)
|
|
1903
1947
|
return result
|
|
1904
|
-
elif (
|
|
1948
|
+
elif isinstance(obj, ListNode):
|
|
1905
1949
|
obj_ref = id(obj)
|
|
1906
1950
|
if obj_ref in node_refs:
|
|
1907
1951
|
return {"__ref__": node_refs[obj_ref]}
|
|
@@ -1914,6 +1958,36 @@ def _serialize(obj, depth=0, node_refs=None):
|
|
|
1914
1958
|
}
|
|
1915
1959
|
result["next"] = _serialize(obj.next, depth + 1, node_refs)
|
|
1916
1960
|
return result
|
|
1961
|
+
elif hasattr(obj, '__dict__'):
|
|
1962
|
+
obj_ref = id(obj)
|
|
1963
|
+
if obj_ref in node_refs:
|
|
1964
|
+
return {"__ref__": node_refs[obj_ref]}
|
|
1965
|
+
node_id = f"object-{obj_ref}"
|
|
1966
|
+
node_refs[obj_ref] = node_id
|
|
1967
|
+
class_name = getattr(getattr(obj, '__class__', None), '__name__', 'object')
|
|
1968
|
+
result = {
|
|
1969
|
+
"__type__": "object",
|
|
1970
|
+
"__class__": class_name,
|
|
1971
|
+
"__id__": node_id,
|
|
1972
|
+
}
|
|
1973
|
+
try:
|
|
1974
|
+
raw_fields = getattr(obj, '__dict__', None)
|
|
1975
|
+
except Exception:
|
|
1976
|
+
raw_fields = None
|
|
1977
|
+
if isinstance(raw_fields, dict):
|
|
1978
|
+
added = 0
|
|
1979
|
+
for key, value in raw_fields.items():
|
|
1980
|
+
key_str = str(key)
|
|
1981
|
+
if key_str.startswith('_'):
|
|
1982
|
+
continue
|
|
1983
|
+
if callable(value):
|
|
1984
|
+
continue
|
|
1985
|
+
result[key_str] = _serialize(value, depth + 1, node_refs)
|
|
1986
|
+
added += 1
|
|
1987
|
+
if added >= _MAX_OBJECT_FIELDS:
|
|
1988
|
+
result["__truncated__"] = True
|
|
1989
|
+
break
|
|
1990
|
+
return result
|
|
1917
1991
|
elif callable(obj):
|
|
1918
1992
|
# Skip functions entirely - return sentinel
|
|
1919
1993
|
return _SKIP_SENTINEL
|
|
@@ -1949,14 +2023,14 @@ def _serialize(obj, depth=0):
|
|
|
1949
2023
|
return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
|
|
1950
2024
|
except TypeError:
|
|
1951
2025
|
return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
|
|
1952
|
-
elif (
|
|
2026
|
+
elif isinstance(obj, TreeNode):
|
|
1953
2027
|
result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
|
|
1954
2028
|
if hasattr(obj, 'left'):
|
|
1955
2029
|
result["left"] = _serialize(obj.left, depth + 1)
|
|
1956
2030
|
if hasattr(obj, 'right'):
|
|
1957
2031
|
result["right"] = _serialize(obj.right, depth + 1)
|
|
1958
2032
|
return result
|
|
1959
|
-
elif (
|
|
2033
|
+
elif isinstance(obj, ListNode):
|
|
1960
2034
|
result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
|
|
1961
2035
|
result["next"] = _serialize(obj.next, depth + 1)
|
|
1962
2036
|
return result
|
|
@@ -2031,14 +2105,14 @@ def _serialize(obj, depth=0):
|
|
|
2031
2105
|
return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
|
|
2032
2106
|
except TypeError:
|
|
2033
2107
|
return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
|
|
2034
|
-
elif
|
|
2108
|
+
elif isinstance(obj, TreeNode):
|
|
2035
2109
|
result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
|
|
2036
2110
|
if hasattr(obj, 'left'):
|
|
2037
2111
|
result["left"] = _serialize(obj.left, depth + 1)
|
|
2038
2112
|
if hasattr(obj, 'right'):
|
|
2039
2113
|
result["right"] = _serialize(obj.right, depth + 1)
|
|
2040
2114
|
return result
|
|
2041
|
-
elif
|
|
2115
|
+
elif isinstance(obj, ListNode):
|
|
2042
2116
|
result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
|
|
2043
2117
|
result["next"] = _serialize(obj.next, depth + 1)
|
|
2044
2118
|
return result
|
|
@@ -2132,16 +2206,28 @@ function createConsoleProxy(output) {
|
|
|
2132
2206
|
}
|
|
2133
2207
|
function isLikelyTreeNodeValue(value) {
|
|
2134
2208
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2135
|
-
const
|
|
2136
|
-
|
|
2137
|
-
|
|
2209
|
+
const record = value;
|
|
2210
|
+
if (record.__type__ === "TreeNode") return true;
|
|
2211
|
+
const ctor = value.constructor;
|
|
2212
|
+
return ctor?.name === "TreeNode";
|
|
2138
2213
|
}
|
|
2139
2214
|
function isLikelyListNodeValue(value) {
|
|
2140
2215
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2141
|
-
const
|
|
2142
|
-
|
|
2143
|
-
const
|
|
2144
|
-
return
|
|
2216
|
+
const record = value;
|
|
2217
|
+
if (record.__type__ === "ListNode") return true;
|
|
2218
|
+
const ctor = value.constructor;
|
|
2219
|
+
return ctor?.name === "ListNode";
|
|
2220
|
+
}
|
|
2221
|
+
function getCustomClassName(value) {
|
|
2222
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
2223
|
+
if (value instanceof Map || value instanceof Set) return null;
|
|
2224
|
+
if (isLikelyTreeNodeValue(value) || isLikelyListNodeValue(value)) return null;
|
|
2225
|
+
const ctor = value.constructor;
|
|
2226
|
+
const name = typeof ctor?.name === "string" ? ctor.name : "";
|
|
2227
|
+
if (!name || name === "Object" || name === "Array" || name === "Map" || name === "Set") {
|
|
2228
|
+
return null;
|
|
2229
|
+
}
|
|
2230
|
+
return name;
|
|
2145
2231
|
}
|
|
2146
2232
|
function serializeValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(), nodeRefState = { ids: /* @__PURE__ */ new Map(), nextId: 1 }) {
|
|
2147
2233
|
if (depth > 48) return "<max depth>";
|
|
@@ -2185,22 +2271,47 @@ function serializeValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(),
|
|
|
2185
2271
|
const nodePrefix = isTree ? "tree" : "list";
|
|
2186
2272
|
const nodeId = `${nodePrefix}-${nodeRefState.nextId++}`;
|
|
2187
2273
|
nodeRefState.ids.set(objectValue, nodeId);
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
};
|
|
2196
|
-
}
|
|
2197
|
-
return {
|
|
2274
|
+
const out2 = isTree ? {
|
|
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
|
+
} : {
|
|
2198
2281
|
__type__: "ListNode",
|
|
2199
2282
|
__id__: nodeId,
|
|
2200
2283
|
val: serializeValue(nodeValue.val ?? nodeValue.value ?? null, depth + 1, seen, nodeRefState),
|
|
2201
2284
|
next: serializeValue(nodeValue.next ?? null, depth + 1, seen, nodeRefState),
|
|
2202
2285
|
..."prev" in nodeValue ? { prev: serializeValue(nodeValue.prev ?? null, depth + 1, seen, nodeRefState) } : {}
|
|
2203
2286
|
};
|
|
2287
|
+
const skipped = isTree ? /* @__PURE__ */ new Set(["__id__", "__type__", "__class__", "val", "value", "left", "right"]) : /* @__PURE__ */ new Set(["__id__", "__type__", "__class__", "val", "value", "next", "prev"]);
|
|
2288
|
+
for (const [k, v] of Object.entries(nodeValue)) {
|
|
2289
|
+
if (skipped.has(k)) continue;
|
|
2290
|
+
out2[k] = serializeValue(v, depth + 1, seen, nodeRefState);
|
|
2291
|
+
}
|
|
2292
|
+
return out2;
|
|
2293
|
+
}
|
|
2294
|
+
const customClassName = getCustomClassName(value);
|
|
2295
|
+
if (customClassName) {
|
|
2296
|
+
const objectValue = value;
|
|
2297
|
+
const existingId = nodeRefState.ids.get(objectValue);
|
|
2298
|
+
if (existingId) {
|
|
2299
|
+
return { __ref__: existingId };
|
|
2300
|
+
}
|
|
2301
|
+
const objectId = `object-${nodeRefState.nextId++}`;
|
|
2302
|
+
nodeRefState.ids.set(objectValue, objectId);
|
|
2303
|
+
if (seen.has(objectValue)) return { __ref__: objectId };
|
|
2304
|
+
seen.add(objectValue);
|
|
2305
|
+
const out2 = {
|
|
2306
|
+
__type__: "object",
|
|
2307
|
+
__class__: customClassName,
|
|
2308
|
+
__id__: objectId
|
|
2309
|
+
};
|
|
2310
|
+
for (const [k, v] of Object.entries(value)) {
|
|
2311
|
+
out2[k] = serializeValue(v, depth + 1, seen, nodeRefState);
|
|
2312
|
+
}
|
|
2313
|
+
seen.delete(objectValue);
|
|
2314
|
+
return out2;
|
|
2204
2315
|
}
|
|
2205
2316
|
if (seen.has(value)) return "<cycle>";
|
|
2206
2317
|
seen.add(value);
|
|
@@ -2291,6 +2402,194 @@ function normalizeInputs(inputs) {
|
|
|
2291
2402
|
}
|
|
2292
2403
|
return hydrated;
|
|
2293
2404
|
}
|
|
2405
|
+
function buildTreeNodeFromLevelOrder(values) {
|
|
2406
|
+
if (!Array.isArray(values) || values.length === 0) return null;
|
|
2407
|
+
const firstValue = values[0];
|
|
2408
|
+
if (firstValue === null || firstValue === void 0) return null;
|
|
2409
|
+
const root = {
|
|
2410
|
+
val: firstValue,
|
|
2411
|
+
value: firstValue,
|
|
2412
|
+
left: null,
|
|
2413
|
+
right: null
|
|
2414
|
+
};
|
|
2415
|
+
const queue = [root];
|
|
2416
|
+
let index = 1;
|
|
2417
|
+
while (queue.length > 0 && index < values.length) {
|
|
2418
|
+
const node = queue.shift();
|
|
2419
|
+
if (!node) break;
|
|
2420
|
+
const leftValue = values[index++];
|
|
2421
|
+
if (leftValue !== null && leftValue !== void 0) {
|
|
2422
|
+
const leftNode = {
|
|
2423
|
+
val: leftValue,
|
|
2424
|
+
value: leftValue,
|
|
2425
|
+
left: null,
|
|
2426
|
+
right: null
|
|
2427
|
+
};
|
|
2428
|
+
node.left = leftNode;
|
|
2429
|
+
queue.push(leftNode);
|
|
2430
|
+
}
|
|
2431
|
+
if (index >= values.length) break;
|
|
2432
|
+
const rightValue = values[index++];
|
|
2433
|
+
if (rightValue !== null && rightValue !== void 0) {
|
|
2434
|
+
const rightNode = {
|
|
2435
|
+
val: rightValue,
|
|
2436
|
+
value: rightValue,
|
|
2437
|
+
left: null,
|
|
2438
|
+
right: null
|
|
2439
|
+
};
|
|
2440
|
+
node.right = rightNode;
|
|
2441
|
+
queue.push(rightNode);
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
return root;
|
|
2445
|
+
}
|
|
2446
|
+
function materializeTreeInput(value) {
|
|
2447
|
+
if (value === null || value === void 0) return value;
|
|
2448
|
+
if (Array.isArray(value)) {
|
|
2449
|
+
return buildTreeNodeFromLevelOrder(value);
|
|
2450
|
+
}
|
|
2451
|
+
if (!isPlainObjectRecord(value)) {
|
|
2452
|
+
return value;
|
|
2453
|
+
}
|
|
2454
|
+
const record = value;
|
|
2455
|
+
if (isLikelyTreeNodeValue(record)) {
|
|
2456
|
+
const node = {
|
|
2457
|
+
val: record.val ?? record.value ?? null,
|
|
2458
|
+
value: record.val ?? record.value ?? null,
|
|
2459
|
+
left: materializeTreeInput(record.left ?? null),
|
|
2460
|
+
right: materializeTreeInput(record.right ?? null)
|
|
2461
|
+
};
|
|
2462
|
+
for (const [key, nested] of Object.entries(record)) {
|
|
2463
|
+
if (key === "__id__" || key === "__type__" || key === "val" || key === "value" || key === "left" || key === "right") continue;
|
|
2464
|
+
node[key] = materializeTreeInput(nested);
|
|
2465
|
+
}
|
|
2466
|
+
return node;
|
|
2467
|
+
}
|
|
2468
|
+
const taggedRecord = value;
|
|
2469
|
+
if (taggedRecord.__type__ === "TreeNode") {
|
|
2470
|
+
const node = {
|
|
2471
|
+
val: taggedRecord.val ?? taggedRecord.value ?? null,
|
|
2472
|
+
value: taggedRecord.val ?? taggedRecord.value ?? null,
|
|
2473
|
+
left: materializeTreeInput(taggedRecord.left ?? null),
|
|
2474
|
+
right: materializeTreeInput(taggedRecord.right ?? null)
|
|
2475
|
+
};
|
|
2476
|
+
for (const [key, nested] of Object.entries(taggedRecord)) {
|
|
2477
|
+
if (key === "__id__" || key === "__type__" || key === "val" || key === "value" || key === "left" || key === "right") continue;
|
|
2478
|
+
node[key] = materializeTreeInput(nested);
|
|
2479
|
+
}
|
|
2480
|
+
return node;
|
|
2481
|
+
}
|
|
2482
|
+
return value;
|
|
2483
|
+
}
|
|
2484
|
+
function materializeListInput(value, refs = /* @__PURE__ */ new Map(), materialized = /* @__PURE__ */ new WeakMap()) {
|
|
2485
|
+
if (value === null || value === void 0) return value;
|
|
2486
|
+
if (Array.isArray(value)) {
|
|
2487
|
+
if (value.length === 0) return null;
|
|
2488
|
+
const head = {
|
|
2489
|
+
val: value[0],
|
|
2490
|
+
value: value[0],
|
|
2491
|
+
next: null
|
|
2492
|
+
};
|
|
2493
|
+
let current = head;
|
|
2494
|
+
for (let i = 1; i < value.length; i++) {
|
|
2495
|
+
const nextNode = { val: value[i], value: value[i], next: null };
|
|
2496
|
+
current.next = nextNode;
|
|
2497
|
+
current = nextNode;
|
|
2498
|
+
}
|
|
2499
|
+
return head;
|
|
2500
|
+
}
|
|
2501
|
+
if (!isPlainObjectRecord(value)) {
|
|
2502
|
+
return value;
|
|
2503
|
+
}
|
|
2504
|
+
const record = value;
|
|
2505
|
+
if (typeof record.__ref__ === "string") {
|
|
2506
|
+
return refs.get(record.__ref__) ?? null;
|
|
2507
|
+
}
|
|
2508
|
+
const taggedRecord = value;
|
|
2509
|
+
if (isLikelyListNodeValue(record) || taggedRecord.__type__ === "ListNode") {
|
|
2510
|
+
const existingMaterialized = materialized.get(record);
|
|
2511
|
+
if (existingMaterialized) {
|
|
2512
|
+
return existingMaterialized;
|
|
2513
|
+
}
|
|
2514
|
+
const node = {
|
|
2515
|
+
val: taggedRecord.val ?? taggedRecord.value ?? null,
|
|
2516
|
+
value: taggedRecord.val ?? taggedRecord.value ?? null,
|
|
2517
|
+
next: null
|
|
2518
|
+
};
|
|
2519
|
+
materialized.set(record, node);
|
|
2520
|
+
if (typeof taggedRecord.__id__ === "string" && taggedRecord.__id__.length > 0) {
|
|
2521
|
+
refs.set(taggedRecord.__id__, node);
|
|
2522
|
+
}
|
|
2523
|
+
node.next = materializeListInput(taggedRecord.next ?? null, refs, materialized);
|
|
2524
|
+
for (const [key, nested] of Object.entries(taggedRecord)) {
|
|
2525
|
+
if (key === "__id__" || key === "__type__" || key === "__class__" || key === "val" || key === "value" || key === "next") continue;
|
|
2526
|
+
node[key] = materializeListInput(nested, refs, materialized);
|
|
2527
|
+
}
|
|
2528
|
+
return node;
|
|
2529
|
+
}
|
|
2530
|
+
return value;
|
|
2531
|
+
}
|
|
2532
|
+
function detectMaterializerKind(ts, typeNode) {
|
|
2533
|
+
if (!typeNode) return null;
|
|
2534
|
+
if (ts.isParenthesizedTypeNode(typeNode)) {
|
|
2535
|
+
return detectMaterializerKind(ts, typeNode.type);
|
|
2536
|
+
}
|
|
2537
|
+
if (ts.isUnionTypeNode(typeNode)) {
|
|
2538
|
+
for (const child of typeNode.types) {
|
|
2539
|
+
const resolved = detectMaterializerKind(ts, child);
|
|
2540
|
+
if (resolved) return resolved;
|
|
2541
|
+
}
|
|
2542
|
+
return null;
|
|
2543
|
+
}
|
|
2544
|
+
if (ts.isTypeReferenceNode(typeNode)) {
|
|
2545
|
+
const typeNameText = typeNode.typeName.getText();
|
|
2546
|
+
if (typeNameText === "TreeNode") return "tree";
|
|
2547
|
+
if (typeNameText === "ListNode") return "list";
|
|
2548
|
+
return null;
|
|
2549
|
+
}
|
|
2550
|
+
return null;
|
|
2551
|
+
}
|
|
2552
|
+
function collectInputMaterializers(ts, functionLikeNode) {
|
|
2553
|
+
const out = {};
|
|
2554
|
+
for (const parameter of functionLikeNode.parameters ?? []) {
|
|
2555
|
+
if (!ts.isIdentifier(parameter.name)) continue;
|
|
2556
|
+
if (parameter.name.text === "this") continue;
|
|
2557
|
+
const kind = detectMaterializerKind(ts, parameter.type);
|
|
2558
|
+
if (kind) {
|
|
2559
|
+
out[parameter.name.text] = kind;
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
return out;
|
|
2563
|
+
}
|
|
2564
|
+
async function resolveInputMaterializers(code, functionName, executionStyle, language) {
|
|
2565
|
+
if (!functionName || executionStyle === "ops-class" || language !== "typescript") {
|
|
2566
|
+
return {};
|
|
2567
|
+
}
|
|
2568
|
+
try {
|
|
2569
|
+
const ts = await getTypeScriptModule();
|
|
2570
|
+
const sourceFile = ts.createSourceFile(
|
|
2571
|
+
"runtime-input.ts",
|
|
2572
|
+
code,
|
|
2573
|
+
ts.ScriptTarget.ES2020,
|
|
2574
|
+
true,
|
|
2575
|
+
ts.ScriptKind.TS
|
|
2576
|
+
);
|
|
2577
|
+
const target = findFunctionLikeNode(ts, sourceFile, functionName, executionStyle);
|
|
2578
|
+
if (!target) return {};
|
|
2579
|
+
return collectInputMaterializers(ts, target);
|
|
2580
|
+
} catch {
|
|
2581
|
+
return {};
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
function applyInputMaterializers(inputs, materializers) {
|
|
2585
|
+
if (Object.keys(materializers).length === 0) return inputs;
|
|
2586
|
+
const next = { ...inputs };
|
|
2587
|
+
for (const [name, kind] of Object.entries(materializers)) {
|
|
2588
|
+
if (!Object.prototype.hasOwnProperty.call(next, name)) continue;
|
|
2589
|
+
next[name] = kind === "tree" ? materializeTreeInput(next[name]) : materializeListInput(next[name]);
|
|
2590
|
+
}
|
|
2591
|
+
return next;
|
|
2592
|
+
}
|
|
2294
2593
|
function collectSimpleParameterNames(ts, functionLikeNode) {
|
|
2295
2594
|
const names = [];
|
|
2296
2595
|
for (const parameter of functionLikeNode.parameters ?? []) {
|
|
@@ -2344,14 +2643,20 @@ function findFunctionLikeNode(ts, sourceFile, functionName, executionStyle) {
|
|
|
2344
2643
|
visit(sourceFile);
|
|
2345
2644
|
return found;
|
|
2346
2645
|
}
|
|
2347
|
-
async function resolveOrderedInputKeys(code, functionName, inputs, executionStyle) {
|
|
2646
|
+
async function resolveOrderedInputKeys(code, functionName, inputs, executionStyle, language = "javascript") {
|
|
2348
2647
|
const fallbackKeys = Object.keys(inputs);
|
|
2349
2648
|
if (!functionName || executionStyle === "ops-class" || fallbackKeys.length <= 1) {
|
|
2350
2649
|
return fallbackKeys;
|
|
2351
2650
|
}
|
|
2352
2651
|
try {
|
|
2353
2652
|
const ts = await getTypeScriptModule();
|
|
2354
|
-
const sourceFile = ts.createSourceFile(
|
|
2653
|
+
const sourceFile = ts.createSourceFile(
|
|
2654
|
+
`runtime-input.${language === "typescript" ? "ts" : "js"}`,
|
|
2655
|
+
code,
|
|
2656
|
+
ts.ScriptTarget.ES2020,
|
|
2657
|
+
true,
|
|
2658
|
+
language === "typescript" ? ts.ScriptKind.TS : ts.ScriptKind.JS
|
|
2659
|
+
);
|
|
2355
2660
|
const target = findFunctionLikeNode(ts, sourceFile, functionName, executionStyle);
|
|
2356
2661
|
if (!target) {
|
|
2357
2662
|
return fallbackKeys;
|
|
@@ -2495,20 +2800,22 @@ async function transpileTypeScript(code) {
|
|
|
2495
2800
|
}
|
|
2496
2801
|
return transpiled.outputText;
|
|
2497
2802
|
}
|
|
2498
|
-
async function executeJavaScriptCode(code, functionName, inputs, executionStyle = "function") {
|
|
2803
|
+
async function executeJavaScriptCode(code, functionName, inputs, executionStyle = "function", language = "javascript") {
|
|
2499
2804
|
const consoleOutput = [];
|
|
2500
2805
|
const consoleProxy = createConsoleProxy(consoleOutput);
|
|
2501
2806
|
const normalizedInputs = normalizeInputs(inputs);
|
|
2807
|
+
const materializers = await resolveInputMaterializers(code, functionName, executionStyle, language);
|
|
2808
|
+
const materializedInputs = applyInputMaterializers(normalizedInputs, materializers);
|
|
2502
2809
|
try {
|
|
2503
2810
|
let output;
|
|
2504
2811
|
if (executionStyle === "ops-class") {
|
|
2505
|
-
const { operations, argumentsList } = getOpsClassInputs(
|
|
2812
|
+
const { operations, argumentsList } = getOpsClassInputs(materializedInputs);
|
|
2506
2813
|
const runner = buildRunner(code, executionStyle, []);
|
|
2507
2814
|
output = await Promise.resolve(runner(consoleProxy, functionName, operations, argumentsList));
|
|
2508
2815
|
} else {
|
|
2509
|
-
const inputKeys = await resolveOrderedInputKeys(code, functionName,
|
|
2816
|
+
const inputKeys = await resolveOrderedInputKeys(code, functionName, materializedInputs, executionStyle, language);
|
|
2510
2817
|
const argNames = inputKeys.map((_, index) => `__arg${index}`);
|
|
2511
|
-
const argValues = inputKeys.map((key) =>
|
|
2818
|
+
const argValues = inputKeys.map((key) => materializedInputs[key]);
|
|
2512
2819
|
const runner = buildRunner(code, executionStyle, argNames);
|
|
2513
2820
|
output = await Promise.resolve(runner(consoleProxy, functionName, ...argValues));
|
|
2514
2821
|
}
|
|
@@ -2527,9 +2834,9 @@ async function executeJavaScriptCode(code, functionName, inputs, executionStyle
|
|
|
2527
2834
|
};
|
|
2528
2835
|
}
|
|
2529
2836
|
}
|
|
2530
|
-
async function executeJavaScriptWithTracing(code, functionName, inputs, executionStyle = "function") {
|
|
2837
|
+
async function executeJavaScriptWithTracing(code, functionName, inputs, executionStyle = "function", language = "javascript") {
|
|
2531
2838
|
const startedAt = performanceNow();
|
|
2532
|
-
const codeResult = await executeJavaScriptCode(code, functionName ?? "", inputs, executionStyle);
|
|
2839
|
+
const codeResult = await executeJavaScriptCode(code, functionName ?? "", inputs, executionStyle, language);
|
|
2533
2840
|
const executionTimeMs = performanceNow() - startedAt;
|
|
2534
2841
|
if (!codeResult.success) {
|
|
2535
2842
|
return {
|
|
@@ -2554,8 +2861,11 @@ async function executeJavaScriptWithTracing(code, functionName, inputs, executio
|
|
|
2554
2861
|
};
|
|
2555
2862
|
}
|
|
2556
2863
|
async function executeTypeScriptCode(code, functionName, inputs, executionStyle = "function") {
|
|
2864
|
+
const normalizedInputs = normalizeInputs(inputs);
|
|
2865
|
+
const materializers = await resolveInputMaterializers(code, functionName, executionStyle, "typescript");
|
|
2866
|
+
const materializedInputs = applyInputMaterializers(normalizedInputs, materializers);
|
|
2557
2867
|
const transpiledCode = await transpileTypeScript(code);
|
|
2558
|
-
return executeJavaScriptCode(transpiledCode, functionName,
|
|
2868
|
+
return executeJavaScriptCode(transpiledCode, functionName, materializedInputs, executionStyle, "typescript");
|
|
2559
2869
|
}
|
|
2560
2870
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2561
2871
|
0 && (module.exports = {
|