@tracecode/harness 0.4.0 → 0.5.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.
- package/CHANGELOG.md +15 -0
- 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 +305 -13
- 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 +305 -13
- 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 +227 -9
- 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 +227 -9
- package/dist/javascript.js.map +1 -1
- package/dist/python.cjs +62 -0
- package/dist/python.cjs.map +1 -1
- package/dist/python.d.cts +2 -2
- package/dist/python.d.ts +2 -2
- package/dist/python.js +62 -0
- 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 +12 -10
- 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:
|
|
@@ -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
|
|
@@ -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:
|
|
@@ -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
|
|
@@ -2143,6 +2217,17 @@ function isLikelyListNodeValue(value) {
|
|
|
2143
2217
|
const hasListLinks = "next" in value || "prev" in value;
|
|
2144
2218
|
return hasValue && hasListLinks && !hasTreeLinks;
|
|
2145
2219
|
}
|
|
2220
|
+
function getCustomClassName(value) {
|
|
2221
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
2222
|
+
if (value instanceof Map || value instanceof Set) return null;
|
|
2223
|
+
if (isLikelyTreeNodeValue(value) || isLikelyListNodeValue(value)) return null;
|
|
2224
|
+
const ctor = value.constructor;
|
|
2225
|
+
const name = typeof ctor?.name === "string" ? ctor.name : "";
|
|
2226
|
+
if (!name || name === "Object" || name === "Array" || name === "Map" || name === "Set") {
|
|
2227
|
+
return null;
|
|
2228
|
+
}
|
|
2229
|
+
return name;
|
|
2230
|
+
}
|
|
2146
2231
|
function serializeValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(), nodeRefState = { ids: /* @__PURE__ */ new Map(), nextId: 1 }) {
|
|
2147
2232
|
if (depth > 48) return "<max depth>";
|
|
2148
2233
|
if (value === null || value === void 0) return value;
|
|
@@ -2202,6 +2287,28 @@ function serializeValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(),
|
|
|
2202
2287
|
..."prev" in nodeValue ? { prev: serializeValue(nodeValue.prev ?? null, depth + 1, seen, nodeRefState) } : {}
|
|
2203
2288
|
};
|
|
2204
2289
|
}
|
|
2290
|
+
const customClassName = getCustomClassName(value);
|
|
2291
|
+
if (customClassName) {
|
|
2292
|
+
const objectValue = value;
|
|
2293
|
+
const existingId = nodeRefState.ids.get(objectValue);
|
|
2294
|
+
if (existingId) {
|
|
2295
|
+
return { __ref__: existingId };
|
|
2296
|
+
}
|
|
2297
|
+
const objectId = `object-${nodeRefState.nextId++}`;
|
|
2298
|
+
nodeRefState.ids.set(objectValue, objectId);
|
|
2299
|
+
if (seen.has(objectValue)) return { __ref__: objectId };
|
|
2300
|
+
seen.add(objectValue);
|
|
2301
|
+
const out2 = {
|
|
2302
|
+
__type__: "object",
|
|
2303
|
+
__class__: customClassName,
|
|
2304
|
+
__id__: objectId
|
|
2305
|
+
};
|
|
2306
|
+
for (const [k, v] of Object.entries(value)) {
|
|
2307
|
+
out2[k] = serializeValue(v, depth + 1, seen, nodeRefState);
|
|
2308
|
+
}
|
|
2309
|
+
seen.delete(objectValue);
|
|
2310
|
+
return out2;
|
|
2311
|
+
}
|
|
2205
2312
|
if (seen.has(value)) return "<cycle>";
|
|
2206
2313
|
seen.add(value);
|
|
2207
2314
|
const out = {};
|
|
@@ -2291,6 +2398,180 @@ function normalizeInputs(inputs) {
|
|
|
2291
2398
|
}
|
|
2292
2399
|
return hydrated;
|
|
2293
2400
|
}
|
|
2401
|
+
function buildTreeNodeFromLevelOrder(values) {
|
|
2402
|
+
if (!Array.isArray(values) || values.length === 0) return null;
|
|
2403
|
+
const firstValue = values[0];
|
|
2404
|
+
if (firstValue === null || firstValue === void 0) return null;
|
|
2405
|
+
const root = {
|
|
2406
|
+
val: firstValue,
|
|
2407
|
+
value: firstValue,
|
|
2408
|
+
left: null,
|
|
2409
|
+
right: null
|
|
2410
|
+
};
|
|
2411
|
+
const queue = [root];
|
|
2412
|
+
let index = 1;
|
|
2413
|
+
while (queue.length > 0 && index < values.length) {
|
|
2414
|
+
const node = queue.shift();
|
|
2415
|
+
if (!node) break;
|
|
2416
|
+
const leftValue = values[index++];
|
|
2417
|
+
if (leftValue !== null && leftValue !== void 0) {
|
|
2418
|
+
const leftNode = {
|
|
2419
|
+
val: leftValue,
|
|
2420
|
+
value: leftValue,
|
|
2421
|
+
left: null,
|
|
2422
|
+
right: null
|
|
2423
|
+
};
|
|
2424
|
+
node.left = leftNode;
|
|
2425
|
+
queue.push(leftNode);
|
|
2426
|
+
}
|
|
2427
|
+
if (index >= values.length) break;
|
|
2428
|
+
const rightValue = values[index++];
|
|
2429
|
+
if (rightValue !== null && rightValue !== void 0) {
|
|
2430
|
+
const rightNode = {
|
|
2431
|
+
val: rightValue,
|
|
2432
|
+
value: rightValue,
|
|
2433
|
+
left: null,
|
|
2434
|
+
right: null
|
|
2435
|
+
};
|
|
2436
|
+
node.right = rightNode;
|
|
2437
|
+
queue.push(rightNode);
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
return root;
|
|
2441
|
+
}
|
|
2442
|
+
function materializeTreeInput(value) {
|
|
2443
|
+
if (value === null || value === void 0) return value;
|
|
2444
|
+
if (Array.isArray(value)) {
|
|
2445
|
+
return buildTreeNodeFromLevelOrder(value);
|
|
2446
|
+
}
|
|
2447
|
+
if (!isPlainObjectRecord(value)) {
|
|
2448
|
+
return value;
|
|
2449
|
+
}
|
|
2450
|
+
const record = value;
|
|
2451
|
+
if (isLikelyTreeNodeValue(record)) {
|
|
2452
|
+
return {
|
|
2453
|
+
val: record.val ?? record.value ?? null,
|
|
2454
|
+
value: record.val ?? record.value ?? null,
|
|
2455
|
+
left: materializeTreeInput(record.left ?? null),
|
|
2456
|
+
right: materializeTreeInput(record.right ?? null)
|
|
2457
|
+
};
|
|
2458
|
+
}
|
|
2459
|
+
const taggedRecord = value;
|
|
2460
|
+
if (taggedRecord.__type__ === "TreeNode") {
|
|
2461
|
+
return {
|
|
2462
|
+
val: taggedRecord.val ?? taggedRecord.value ?? null,
|
|
2463
|
+
value: taggedRecord.val ?? taggedRecord.value ?? null,
|
|
2464
|
+
left: materializeTreeInput(taggedRecord.left ?? null),
|
|
2465
|
+
right: materializeTreeInput(taggedRecord.right ?? null)
|
|
2466
|
+
};
|
|
2467
|
+
}
|
|
2468
|
+
return value;
|
|
2469
|
+
}
|
|
2470
|
+
function materializeListInput(value, refs = /* @__PURE__ */ new Map(), materialized = /* @__PURE__ */ new WeakMap()) {
|
|
2471
|
+
if (value === null || value === void 0) return value;
|
|
2472
|
+
if (Array.isArray(value)) {
|
|
2473
|
+
if (value.length === 0) return null;
|
|
2474
|
+
const head = {
|
|
2475
|
+
val: value[0],
|
|
2476
|
+
value: value[0],
|
|
2477
|
+
next: null
|
|
2478
|
+
};
|
|
2479
|
+
let current = head;
|
|
2480
|
+
for (let i = 1; i < value.length; i++) {
|
|
2481
|
+
const nextNode = { val: value[i], value: value[i], next: null };
|
|
2482
|
+
current.next = nextNode;
|
|
2483
|
+
current = nextNode;
|
|
2484
|
+
}
|
|
2485
|
+
return head;
|
|
2486
|
+
}
|
|
2487
|
+
if (!isPlainObjectRecord(value)) {
|
|
2488
|
+
return value;
|
|
2489
|
+
}
|
|
2490
|
+
const record = value;
|
|
2491
|
+
if (typeof record.__ref__ === "string") {
|
|
2492
|
+
return refs.get(record.__ref__) ?? null;
|
|
2493
|
+
}
|
|
2494
|
+
const taggedRecord = value;
|
|
2495
|
+
if (isLikelyListNodeValue(record) || taggedRecord.__type__ === "ListNode") {
|
|
2496
|
+
const existingMaterialized = materialized.get(record);
|
|
2497
|
+
if (existingMaterialized) {
|
|
2498
|
+
return existingMaterialized;
|
|
2499
|
+
}
|
|
2500
|
+
const node = {
|
|
2501
|
+
val: taggedRecord.val ?? taggedRecord.value ?? null,
|
|
2502
|
+
value: taggedRecord.val ?? taggedRecord.value ?? null,
|
|
2503
|
+
next: null
|
|
2504
|
+
};
|
|
2505
|
+
materialized.set(record, node);
|
|
2506
|
+
if (typeof taggedRecord.__id__ === "string" && taggedRecord.__id__.length > 0) {
|
|
2507
|
+
refs.set(taggedRecord.__id__, node);
|
|
2508
|
+
}
|
|
2509
|
+
node.next = materializeListInput(taggedRecord.next ?? null, refs, materialized);
|
|
2510
|
+
return node;
|
|
2511
|
+
}
|
|
2512
|
+
return value;
|
|
2513
|
+
}
|
|
2514
|
+
function detectMaterializerKind(ts, typeNode) {
|
|
2515
|
+
if (!typeNode) return null;
|
|
2516
|
+
if (ts.isParenthesizedTypeNode(typeNode)) {
|
|
2517
|
+
return detectMaterializerKind(ts, typeNode.type);
|
|
2518
|
+
}
|
|
2519
|
+
if (ts.isUnionTypeNode(typeNode)) {
|
|
2520
|
+
for (const child of typeNode.types) {
|
|
2521
|
+
const resolved = detectMaterializerKind(ts, child);
|
|
2522
|
+
if (resolved) return resolved;
|
|
2523
|
+
}
|
|
2524
|
+
return null;
|
|
2525
|
+
}
|
|
2526
|
+
if (ts.isTypeReferenceNode(typeNode)) {
|
|
2527
|
+
const typeNameText = typeNode.typeName.getText();
|
|
2528
|
+
if (typeNameText === "TreeNode") return "tree";
|
|
2529
|
+
if (typeNameText === "ListNode") return "list";
|
|
2530
|
+
return null;
|
|
2531
|
+
}
|
|
2532
|
+
return null;
|
|
2533
|
+
}
|
|
2534
|
+
function collectInputMaterializers(ts, functionLikeNode) {
|
|
2535
|
+
const out = {};
|
|
2536
|
+
for (const parameter of functionLikeNode.parameters ?? []) {
|
|
2537
|
+
if (!ts.isIdentifier(parameter.name)) continue;
|
|
2538
|
+
if (parameter.name.text === "this") continue;
|
|
2539
|
+
const kind = detectMaterializerKind(ts, parameter.type);
|
|
2540
|
+
if (kind) {
|
|
2541
|
+
out[parameter.name.text] = kind;
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
return out;
|
|
2545
|
+
}
|
|
2546
|
+
async function resolveInputMaterializers(code, functionName, executionStyle, language) {
|
|
2547
|
+
if (!functionName || executionStyle === "ops-class" || language !== "typescript") {
|
|
2548
|
+
return {};
|
|
2549
|
+
}
|
|
2550
|
+
try {
|
|
2551
|
+
const ts = await getTypeScriptModule();
|
|
2552
|
+
const sourceFile = ts.createSourceFile(
|
|
2553
|
+
"runtime-input.ts",
|
|
2554
|
+
code,
|
|
2555
|
+
ts.ScriptTarget.ES2020,
|
|
2556
|
+
true,
|
|
2557
|
+
ts.ScriptKind.TS
|
|
2558
|
+
);
|
|
2559
|
+
const target = findFunctionLikeNode(ts, sourceFile, functionName, executionStyle);
|
|
2560
|
+
if (!target) return {};
|
|
2561
|
+
return collectInputMaterializers(ts, target);
|
|
2562
|
+
} catch {
|
|
2563
|
+
return {};
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
function applyInputMaterializers(inputs, materializers) {
|
|
2567
|
+
if (Object.keys(materializers).length === 0) return inputs;
|
|
2568
|
+
const next = { ...inputs };
|
|
2569
|
+
for (const [name, kind] of Object.entries(materializers)) {
|
|
2570
|
+
if (!Object.prototype.hasOwnProperty.call(next, name)) continue;
|
|
2571
|
+
next[name] = kind === "tree" ? materializeTreeInput(next[name]) : materializeListInput(next[name]);
|
|
2572
|
+
}
|
|
2573
|
+
return next;
|
|
2574
|
+
}
|
|
2294
2575
|
function collectSimpleParameterNames(ts, functionLikeNode) {
|
|
2295
2576
|
const names = [];
|
|
2296
2577
|
for (const parameter of functionLikeNode.parameters ?? []) {
|
|
@@ -2344,14 +2625,20 @@ function findFunctionLikeNode(ts, sourceFile, functionName, executionStyle) {
|
|
|
2344
2625
|
visit(sourceFile);
|
|
2345
2626
|
return found;
|
|
2346
2627
|
}
|
|
2347
|
-
async function resolveOrderedInputKeys(code, functionName, inputs, executionStyle) {
|
|
2628
|
+
async function resolveOrderedInputKeys(code, functionName, inputs, executionStyle, language = "javascript") {
|
|
2348
2629
|
const fallbackKeys = Object.keys(inputs);
|
|
2349
2630
|
if (!functionName || executionStyle === "ops-class" || fallbackKeys.length <= 1) {
|
|
2350
2631
|
return fallbackKeys;
|
|
2351
2632
|
}
|
|
2352
2633
|
try {
|
|
2353
2634
|
const ts = await getTypeScriptModule();
|
|
2354
|
-
const sourceFile = ts.createSourceFile(
|
|
2635
|
+
const sourceFile = ts.createSourceFile(
|
|
2636
|
+
`runtime-input.${language === "typescript" ? "ts" : "js"}`,
|
|
2637
|
+
code,
|
|
2638
|
+
ts.ScriptTarget.ES2020,
|
|
2639
|
+
true,
|
|
2640
|
+
language === "typescript" ? ts.ScriptKind.TS : ts.ScriptKind.JS
|
|
2641
|
+
);
|
|
2355
2642
|
const target = findFunctionLikeNode(ts, sourceFile, functionName, executionStyle);
|
|
2356
2643
|
if (!target) {
|
|
2357
2644
|
return fallbackKeys;
|
|
@@ -2495,20 +2782,22 @@ async function transpileTypeScript(code) {
|
|
|
2495
2782
|
}
|
|
2496
2783
|
return transpiled.outputText;
|
|
2497
2784
|
}
|
|
2498
|
-
async function executeJavaScriptCode(code, functionName, inputs, executionStyle = "function") {
|
|
2785
|
+
async function executeJavaScriptCode(code, functionName, inputs, executionStyle = "function", language = "javascript") {
|
|
2499
2786
|
const consoleOutput = [];
|
|
2500
2787
|
const consoleProxy = createConsoleProxy(consoleOutput);
|
|
2501
2788
|
const normalizedInputs = normalizeInputs(inputs);
|
|
2789
|
+
const materializers = await resolveInputMaterializers(code, functionName, executionStyle, language);
|
|
2790
|
+
const materializedInputs = applyInputMaterializers(normalizedInputs, materializers);
|
|
2502
2791
|
try {
|
|
2503
2792
|
let output;
|
|
2504
2793
|
if (executionStyle === "ops-class") {
|
|
2505
|
-
const { operations, argumentsList } = getOpsClassInputs(
|
|
2794
|
+
const { operations, argumentsList } = getOpsClassInputs(materializedInputs);
|
|
2506
2795
|
const runner = buildRunner(code, executionStyle, []);
|
|
2507
2796
|
output = await Promise.resolve(runner(consoleProxy, functionName, operations, argumentsList));
|
|
2508
2797
|
} else {
|
|
2509
|
-
const inputKeys = await resolveOrderedInputKeys(code, functionName,
|
|
2798
|
+
const inputKeys = await resolveOrderedInputKeys(code, functionName, materializedInputs, executionStyle, language);
|
|
2510
2799
|
const argNames = inputKeys.map((_, index) => `__arg${index}`);
|
|
2511
|
-
const argValues = inputKeys.map((key) =>
|
|
2800
|
+
const argValues = inputKeys.map((key) => materializedInputs[key]);
|
|
2512
2801
|
const runner = buildRunner(code, executionStyle, argNames);
|
|
2513
2802
|
output = await Promise.resolve(runner(consoleProxy, functionName, ...argValues));
|
|
2514
2803
|
}
|
|
@@ -2527,9 +2816,9 @@ async function executeJavaScriptCode(code, functionName, inputs, executionStyle
|
|
|
2527
2816
|
};
|
|
2528
2817
|
}
|
|
2529
2818
|
}
|
|
2530
|
-
async function executeJavaScriptWithTracing(code, functionName, inputs, executionStyle = "function") {
|
|
2819
|
+
async function executeJavaScriptWithTracing(code, functionName, inputs, executionStyle = "function", language = "javascript") {
|
|
2531
2820
|
const startedAt = performanceNow();
|
|
2532
|
-
const codeResult = await executeJavaScriptCode(code, functionName ?? "", inputs, executionStyle);
|
|
2821
|
+
const codeResult = await executeJavaScriptCode(code, functionName ?? "", inputs, executionStyle, language);
|
|
2533
2822
|
const executionTimeMs = performanceNow() - startedAt;
|
|
2534
2823
|
if (!codeResult.success) {
|
|
2535
2824
|
return {
|
|
@@ -2554,8 +2843,11 @@ async function executeJavaScriptWithTracing(code, functionName, inputs, executio
|
|
|
2554
2843
|
};
|
|
2555
2844
|
}
|
|
2556
2845
|
async function executeTypeScriptCode(code, functionName, inputs, executionStyle = "function") {
|
|
2846
|
+
const normalizedInputs = normalizeInputs(inputs);
|
|
2847
|
+
const materializers = await resolveInputMaterializers(code, functionName, executionStyle, "typescript");
|
|
2848
|
+
const materializedInputs = applyInputMaterializers(normalizedInputs, materializers);
|
|
2557
2849
|
const transpiledCode = await transpileTypeScript(code);
|
|
2558
|
-
return executeJavaScriptCode(transpiledCode, functionName,
|
|
2850
|
+
return executeJavaScriptCode(transpiledCode, functionName, materializedInputs, executionStyle, "typescript");
|
|
2559
2851
|
}
|
|
2560
2852
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2561
2853
|
0 && (module.exports = {
|