mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
chore: integrate concurrent main changes with the dylib fix
Preserve the upstream WAT framing optimization alongside the qualified dylib fix. The combined tree passes 14 compiled dylib CLI tests and the full check:ci gate.
This commit is contained in:
commit
3a0e91dd91
8 files changed
+944
-22
No files matched your search
@@ -1,5 +1,9 @@
|
||||
# Analysis efficiency measurements
|
||||
|
||||
The [WAT framing checkpoint](wasm-string-framing.md) measures structural scanning
|
||||
on real SQLite and VS Code components, with unchanged Evidence and token costs,
|
||||
small whole-task timing gains and no memory improvement.
|
||||
|
||||
The [native inventory view checkpoint](native-inventory-views.md) compares
|
||||
complete delivery with summaries and selected rows on real `true` and jq
|
||||
inventories, including oversized-response recovery, portable old Evidence,
|
||||
|
||||
@@ -0,0 +1,561 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"issue": 5760,
|
||||
"baseline_source": "d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f",
|
||||
"candidate_code_source": "9776d78f6c799cba8d8cf5c9b3139a86449eaebd",
|
||||
"integration_base": "335c042d166b2c8b2c0600935cf77607ae11edbc",
|
||||
"toolchain": {
|
||||
"node": "24.18.0",
|
||||
"npm": "11.16.0",
|
||||
"wabt": "1.0.42",
|
||||
"tokenizer": "0.12.0",
|
||||
"encoding": "cl100k_base"
|
||||
},
|
||||
"catalog_sha256": "4586abd317171cbb307295cc687c24f7f45e603959538643325895b546a38242",
|
||||
"catalog_tools": 212,
|
||||
"package_lock_sha256": "699a14749e3825c62430faeb18224190fee1c9347760494e38e334e180bea6ec",
|
||||
"runtime_mcp_sha256": {
|
||||
"baseline": "fa6831f05d97b6b28642b709b5497e351d2ee632dd1abc0d2f87a648057afe87",
|
||||
"candidate": "e4af82d847fe3d9816f4f7ae1f584ef129ba151bc5a6f95080a7519fd08be2cf"
|
||||
},
|
||||
"sources_sha256": {
|
||||
"WabtString.ts": "398f3cd98c087740a553768d10c21912d28f33e13bdab589eec760da4ed0b9fd",
|
||||
"WabtWat.ts": "70fb9acfbe747be4fa5d8be235012a88f94485bc0baf0fbba1fe22f18b87f44b",
|
||||
"WabtInterface.ts": "1a63c834a46268bbaf97e6eb39a99b3ccd3f2893527749d65ee6f5026bc2782a"
|
||||
},
|
||||
"native_tools_sha256": {
|
||||
"wasm-validate": "6b722ed0df68204cfc7a8effdf1fc2ddeac2d184bd211cdf7fdfa5f9d49d3eb5",
|
||||
"wasm-objdump": "dad264def1a3b7755859c5bf48227f01259a95fa82b7c38358b12b9e70b27a41",
|
||||
"wasm2wat": "4322d652f650c1ee117b549c9722f42fc93eb4676ff046d60ba033b5639697a5"
|
||||
},
|
||||
"artifacts": {
|
||||
"small": {
|
||||
"sha256": "f399acbd52258f950f24dd5ca4a82674f1f26cea60e7be7c5daaade568768fda",
|
||||
"bytes": 80,
|
||||
"wat_sha256": "918ecd8a14daf20b58707d0879efda8b38df37f219279688b3aa3a812ae5646a",
|
||||
"wat_bytes": 270,
|
||||
"answer_normalized_sha256": "8eb8aedcf17bac4a98d34f5a004b5541f671350f94918575e2fc4eee9fd2db29",
|
||||
"parent_evidence_id": "ev_88b35d9f926672b9e42fc4e1514090eaf2f99bb918439f1270dd53f7fe684e74"
|
||||
},
|
||||
"sqlite": {
|
||||
"sha256": "2ee8f3dab694532afc8840e07703127287662d08b74e6ff50491ce63f00d5752",
|
||||
"bytes": 868907,
|
||||
"wat_sha256": "7b1f8cd4fcbf310f4203ce64e15b4eb068ecdf29838551137245efecb7283f81",
|
||||
"wat_bytes": 15382128,
|
||||
"answer_normalized_sha256": "330b84e01541f70a964c826754da3e5f49a1bb1bd535ae1d1f00fb44a1157ff6",
|
||||
"parent_evidence_id": "ev_899ecb126cd0a283169641085fa10e46460504bf8bc8eba69580fa6d641e431e"
|
||||
},
|
||||
"css": {
|
||||
"sha256": "8a23977fe271357cce6f254ef88c9bebf3854602d8046605aef6a45c02135c59",
|
||||
"bytes": 128668,
|
||||
"wat_sha256": "c53273cb7da0867ac52490d083c7952fcc538b3848c6d0d1f2e2621e2ded23c0",
|
||||
"wat_bytes": 13599679,
|
||||
"answer_normalized_sha256": "3d301feaa48a646c4d9f2a026353544519cc4694c9840b1c764d81ec9ba7fb65",
|
||||
"parent_evidence_id": "ev_27108db83ae4d0a9289c23dace9c0e9e6d573f72f1e982b490c7f45394ba702c"
|
||||
}
|
||||
},
|
||||
"samples": [
|
||||
{
|
||||
"case": "small",
|
||||
"lane": "baseline",
|
||||
"round": 1,
|
||||
"wall_seconds": 12.417,
|
||||
"cpu_seconds": 12.114979,
|
||||
"memory_peak_bytes": 823410688,
|
||||
"transport_proxy_tokens": 894936,
|
||||
"fresh_inspect_ms": 1781.0228269999998,
|
||||
"repeat_inspect_ms": 1793.3802260000011,
|
||||
"reply_bytes": 36180,
|
||||
"raw_guard_log_sha256": "f4ab763c21c4dd22f07ab978690966fd1efc6961216e41e195316e7330c269d6"
|
||||
},
|
||||
{
|
||||
"case": "small",
|
||||
"lane": "candidate",
|
||||
"round": 1,
|
||||
"wall_seconds": 10.191,
|
||||
"cpu_seconds": 9.868799,
|
||||
"memory_peak_bytes": 829722624,
|
||||
"transport_proxy_tokens": 894936,
|
||||
"fresh_inspect_ms": 1298.6234909999998,
|
||||
"repeat_inspect_ms": 1917.7533390000008,
|
||||
"reply_bytes": 36182,
|
||||
"raw_guard_log_sha256": "5cfd93018a2cabbe5b9fa4b9062fbed8e6da638ad5672fd566f5cf76182fecd5"
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "baseline",
|
||||
"round": 1,
|
||||
"wall_seconds": 14.317,
|
||||
"cpu_seconds": 13.845753,
|
||||
"memory_peak_bytes": 1032982528,
|
||||
"transport_proxy_tokens": 895044,
|
||||
"fresh_inspect_ms": 3405.006531,
|
||||
"repeat_inspect_ms": 3345.840587999999,
|
||||
"reply_bytes": 37248,
|
||||
"raw_guard_log_sha256": "46b1b2e9f02e41be7a7cbae8a311b799ab52148a150ec5c0c683e0745c44ad03"
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "candidate",
|
||||
"round": 1,
|
||||
"wall_seconds": 13.311,
|
||||
"cpu_seconds": 12.956772,
|
||||
"memory_peak_bytes": 1029627904,
|
||||
"transport_proxy_tokens": 895044,
|
||||
"fresh_inspect_ms": 2838.048675,
|
||||
"repeat_inspect_ms": 3233.226218,
|
||||
"reply_bytes": 37250,
|
||||
"raw_guard_log_sha256": "8933144b3f6fd100de72b1c1f22a791b7c4bef74c355bb9211be4c9e9383fe4b"
|
||||
},
|
||||
{
|
||||
"case": "css",
|
||||
"lane": "baseline",
|
||||
"round": 1,
|
||||
"wall_seconds": 13.211,
|
||||
"cpu_seconds": 12.79919,
|
||||
"memory_peak_bytes": 1099599872,
|
||||
"transport_proxy_tokens": 895430,
|
||||
"fresh_inspect_ms": 2823.246057,
|
||||
"repeat_inspect_ms": 3302.541784000001,
|
||||
"reply_bytes": 37426,
|
||||
"raw_guard_log_sha256": "9f4b7dfcd97faf8c85463a4c17f0612b6c37b7e29843f5e52b43df27aaae0ac6"
|
||||
},
|
||||
{
|
||||
"case": "css",
|
||||
"lane": "candidate",
|
||||
"round": 1,
|
||||
"wall_seconds": 12.912,
|
||||
"cpu_seconds": 12.46982,
|
||||
"memory_peak_bytes": 1110261760,
|
||||
"transport_proxy_tokens": 895430,
|
||||
"fresh_inspect_ms": 2839.796418,
|
||||
"repeat_inspect_ms": 3002.9903570000006,
|
||||
"reply_bytes": 37428,
|
||||
"raw_guard_log_sha256": "dc2ed426cd1191ca779a4e736bceb3d0001a5b8344dbba01544ecd91a6bb73b6"
|
||||
},
|
||||
{
|
||||
"case": "small",
|
||||
"lane": "candidate",
|
||||
"round": 2,
|
||||
"wall_seconds": 10.295,
|
||||
"cpu_seconds": 9.986392,
|
||||
"memory_peak_bytes": 807264256,
|
||||
"transport_proxy_tokens": 894936,
|
||||
"fresh_inspect_ms": 1687.949067,
|
||||
"repeat_inspect_ms": 1907.0628659999993,
|
||||
"reply_bytes": 36182,
|
||||
"raw_guard_log_sha256": "376199e896af92b6351d2dde7c765b5aa4b1feac0e9664da934e24732eaa22ec"
|
||||
},
|
||||
{
|
||||
"case": "small",
|
||||
"lane": "baseline",
|
||||
"round": 2,
|
||||
"wall_seconds": 10.192,
|
||||
"cpu_seconds": 9.86319,
|
||||
"memory_peak_bytes": 826806272,
|
||||
"transport_proxy_tokens": 894936,
|
||||
"fresh_inspect_ms": 1621.7653269999996,
|
||||
"repeat_inspect_ms": 1937.1286520000012,
|
||||
"reply_bytes": 36180,
|
||||
"raw_guard_log_sha256": "2d40d7309203eefcb7cbb5a5e81640e728839eb30f29cad017584738ea50616f"
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "candidate",
|
||||
"round": 2,
|
||||
"wall_seconds": 13.52,
|
||||
"cpu_seconds": 13.133355,
|
||||
"memory_peak_bytes": 1211944960,
|
||||
"transport_proxy_tokens": 895044,
|
||||
"fresh_inspect_ms": 3167.13338,
|
||||
"repeat_inspect_ms": 3425.1366179999986,
|
||||
"reply_bytes": 37250,
|
||||
"raw_guard_log_sha256": "a962200a36a2530b044548b475b28d7234f73b875ffbc3fe16ef4b36e61ae49a"
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "baseline",
|
||||
"round": 2,
|
||||
"wall_seconds": 13.515,
|
||||
"cpu_seconds": 13.170183,
|
||||
"memory_peak_bytes": 1017561088,
|
||||
"transport_proxy_tokens": 895044,
|
||||
"fresh_inspect_ms": 3224.859665,
|
||||
"repeat_inspect_ms": 3230.52117,
|
||||
"reply_bytes": 37248,
|
||||
"raw_guard_log_sha256": "0452dae8c26a023bd6220bca03dfd7a58425ef579f8e7964f04b4cb944723f84"
|
||||
},
|
||||
{
|
||||
"case": "css",
|
||||
"lane": "candidate",
|
||||
"round": 2,
|
||||
"wall_seconds": 12.112,
|
||||
"cpu_seconds": 11.727334,
|
||||
"memory_peak_bytes": 1186643968,
|
||||
"transport_proxy_tokens": 895430,
|
||||
"fresh_inspect_ms": 2662.82945,
|
||||
"repeat_inspect_ms": 2489.199032999999,
|
||||
"reply_bytes": 37428,
|
||||
"raw_guard_log_sha256": "9d27bfa9720f4291324aa6fc47e44ffdee8b6fbc63ea29a2c82d297d0ba1f0c6"
|
||||
},
|
||||
{
|
||||
"case": "css",
|
||||
"lane": "baseline",
|
||||
"round": 2,
|
||||
"wall_seconds": 12.409,
|
||||
"cpu_seconds": 12.038676,
|
||||
"memory_peak_bytes": 1079783424,
|
||||
"transport_proxy_tokens": 895430,
|
||||
"fresh_inspect_ms": 2793.9973870000003,
|
||||
"repeat_inspect_ms": 2541.021634999999,
|
||||
"reply_bytes": 37426,
|
||||
"raw_guard_log_sha256": "ddc43e4517a2ed634d5a969104b9051ac4e654485d3552f19d4c141a5834b205"
|
||||
},
|
||||
{
|
||||
"case": "small",
|
||||
"lane": "baseline",
|
||||
"round": 3,
|
||||
"wall_seconds": 9.797,
|
||||
"cpu_seconds": 9.449418,
|
||||
"memory_peak_bytes": 822263808,
|
||||
"transport_proxy_tokens": 894936,
|
||||
"fresh_inspect_ms": 1612.1414539999996,
|
||||
"repeat_inspect_ms": 1833.922163000001,
|
||||
"reply_bytes": 36180,
|
||||
"raw_guard_log_sha256": "92aa46fe57caeae60cb3105b2ac370a8f8463afed4a7f666f46be885cad0ca4d"
|
||||
},
|
||||
{
|
||||
"case": "small",
|
||||
"lane": "candidate",
|
||||
"round": 3,
|
||||
"wall_seconds": 10.192,
|
||||
"cpu_seconds": 9.868713,
|
||||
"memory_peak_bytes": 829575168,
|
||||
"transport_proxy_tokens": 894936,
|
||||
"fresh_inspect_ms": 1629.0064629999997,
|
||||
"repeat_inspect_ms": 1962.5034050000004,
|
||||
"reply_bytes": 36182,
|
||||
"raw_guard_log_sha256": "0451dacd244ced0ac56ceb0f73b39e1b86fa1517a0ec88391a3ab37d45b9bd20"
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "baseline",
|
||||
"round": 3,
|
||||
"wall_seconds": 13.714,
|
||||
"cpu_seconds": 13.319143,
|
||||
"memory_peak_bytes": 1196531712,
|
||||
"transport_proxy_tokens": 895044,
|
||||
"fresh_inspect_ms": 3228.7134460000007,
|
||||
"repeat_inspect_ms": 3397.271211000001,
|
||||
"reply_bytes": 37248,
|
||||
"raw_guard_log_sha256": "d3f7e1e572a4c3251ca479a3c018d2f024b80103e443a8daeb125bd896165d2a"
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "candidate",
|
||||
"round": 3,
|
||||
"wall_seconds": 12.709,
|
||||
"cpu_seconds": 12.349818,
|
||||
"memory_peak_bytes": 1205280768,
|
||||
"transport_proxy_tokens": 895044,
|
||||
"fresh_inspect_ms": 3071.7333470000003,
|
||||
"repeat_inspect_ms": 3024.3819120000007,
|
||||
"reply_bytes": 37250,
|
||||
"raw_guard_log_sha256": "57b405e4a4e8a9acbb4d9e4bb4663d931ad7ffec52a2b6a2969a7362287db892"
|
||||
},
|
||||
{
|
||||
"case": "css",
|
||||
"lane": "baseline",
|
||||
"round": 3,
|
||||
"wall_seconds": 12.315,
|
||||
"cpu_seconds": 11.921752,
|
||||
"memory_peak_bytes": 1081831424,
|
||||
"transport_proxy_tokens": 895430,
|
||||
"fresh_inspect_ms": 2798.227023,
|
||||
"repeat_inspect_ms": 2563.7297770000005,
|
||||
"reply_bytes": 37426,
|
||||
"raw_guard_log_sha256": "2f6fca011f6718111b455d8104121ff6880131f58e0a82df069efef9445f5c07"
|
||||
},
|
||||
{
|
||||
"case": "css",
|
||||
"lane": "candidate",
|
||||
"round": 3,
|
||||
"wall_seconds": 11.901,
|
||||
"cpu_seconds": 11.54646,
|
||||
"memory_peak_bytes": 1123659776,
|
||||
"transport_proxy_tokens": 895430,
|
||||
"fresh_inspect_ms": 2600.1125399999996,
|
||||
"repeat_inspect_ms": 2398.082381,
|
||||
"reply_bytes": 37428,
|
||||
"raw_guard_log_sha256": "180726dbb90af48c442109f75ccc50bf243ebcc8392908f9322eb91100a5f179"
|
||||
}
|
||||
],
|
||||
"parser_samples": [
|
||||
{
|
||||
"case": "small.decoded",
|
||||
"lane": "baseline",
|
||||
"round": 1,
|
||||
"elapsed_ms": [
|
||||
2.9900399999999934, 1.9184900000000056, 0.3164599999999922,
|
||||
0.622399999999999, 0.6818110000000104, 1.7410099999999886
|
||||
],
|
||||
"result_sha256": "beb5c7e4e8da08e3c104753b768c8ca40559d517dba80c483253991721b39c7f",
|
||||
"wall_seconds": 0.422,
|
||||
"cpu_seconds": 0.169929,
|
||||
"memory_peak_bytes": 28078080
|
||||
},
|
||||
{
|
||||
"case": "small.decoded",
|
||||
"lane": "candidate",
|
||||
"round": 1,
|
||||
"elapsed_ms": [
|
||||
3.8333299999999895, 1.5887500000000045, 0.4467700000000008,
|
||||
0.3875499999999903, 0.3238100000000088, 0.21590999999999383
|
||||
],
|
||||
"result_sha256": "beb5c7e4e8da08e3c104753b768c8ca40559d517dba80c483253991721b39c7f",
|
||||
"wall_seconds": 0.323,
|
||||
"cpu_seconds": 0.154998,
|
||||
"memory_peak_bytes": 27508736
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "baseline",
|
||||
"round": 1,
|
||||
"elapsed_ms": [
|
||||
248.049268, 224.29203599999994, 176.49019599999997, 155.392424,
|
||||
162.08057399999996, 172.70000600000003
|
||||
],
|
||||
"result_sha256": "74eb7108ddd459dfa7bfb7a1fe653c8862eb43acd89d91ae033e7ac9158587ce",
|
||||
"wall_seconds": 1.532,
|
||||
"cpu_seconds": 1.326985,
|
||||
"memory_peak_bytes": 71315456
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "candidate",
|
||||
"round": 1,
|
||||
"elapsed_ms": [
|
||||
103.56140300000001, 103.344674, 56.359200999999985, 43.188242,
|
||||
44.79720200000003, 44.11639200000002
|
||||
],
|
||||
"result_sha256": "74eb7108ddd459dfa7bfb7a1fe653c8862eb43acd89d91ae033e7ac9158587ce",
|
||||
"wall_seconds": 0.827,
|
||||
"cpu_seconds": 0.598442,
|
||||
"memory_peak_bytes": 71557120
|
||||
},
|
||||
{
|
||||
"case": "tree-sitter-css",
|
||||
"lane": "baseline",
|
||||
"round": 1,
|
||||
"elapsed_ms": [
|
||||
133.568665, 122.39741400000003, 110.63244400000002, 111.27637299999998,
|
||||
111.761034, 111.34842400000002
|
||||
],
|
||||
"result_sha256": "b59e5bdc32939c215443da6f3ce48e61fe2bfd86ff75b7a85d3c10a93b6fae7e",
|
||||
"wall_seconds": 1.127,
|
||||
"cpu_seconds": 0.882723,
|
||||
"memory_peak_bytes": 55656448
|
||||
},
|
||||
{
|
||||
"case": "tree-sitter-css",
|
||||
"lane": "candidate",
|
||||
"round": 1,
|
||||
"elapsed_ms": [
|
||||
15.454230999999993, 15.1781, 17.94840099999999, 15.499510999999984,
|
||||
15.028279999999995, 2.9674699999999916
|
||||
],
|
||||
"result_sha256": "b59e5bdc32939c215443da6f3ce48e61fe2bfd86ff75b7a85d3c10a93b6fae7e",
|
||||
"wall_seconds": 0.424,
|
||||
"cpu_seconds": 0.255557,
|
||||
"memory_peak_bytes": 54427648
|
||||
},
|
||||
{
|
||||
"case": "small.decoded",
|
||||
"lane": "candidate",
|
||||
"round": 2,
|
||||
"elapsed_ms": [
|
||||
2.492229000000009, 1.6617090000000019, 0.4688189999999963,
|
||||
0.40376000000000545, 0.18850899999999626, 0.19684000000000879
|
||||
],
|
||||
"result_sha256": "beb5c7e4e8da08e3c104753b768c8ca40559d517dba80c483253991721b39c7f",
|
||||
"wall_seconds": 0.324,
|
||||
"cpu_seconds": 0.14932,
|
||||
"memory_peak_bytes": 27750400
|
||||
},
|
||||
{
|
||||
"case": "small.decoded",
|
||||
"lane": "baseline",
|
||||
"round": 2,
|
||||
"elapsed_ms": [
|
||||
3.0103999999999758, 2.4378910000000076, 0.30259000000000924,
|
||||
0.5248499999999865, 0.6185799999999801, 1.3529399999999896
|
||||
],
|
||||
"result_sha256": "beb5c7e4e8da08e3c104753b768c8ca40559d517dba80c483253991721b39c7f",
|
||||
"wall_seconds": 0.428,
|
||||
"cpu_seconds": 0.219561,
|
||||
"memory_peak_bytes": 30007296
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "candidate",
|
||||
"round": 2,
|
||||
"elapsed_ms": [
|
||||
150.102906, 136.73758599999996, 85.33841300000006, 42.61153200000001,
|
||||
45.540752, 43.07188099999996
|
||||
],
|
||||
"result_sha256": "74eb7108ddd459dfa7bfb7a1fe653c8862eb43acd89d91ae033e7ac9158587ce",
|
||||
"wall_seconds": 0.959,
|
||||
"cpu_seconds": 0.738843,
|
||||
"memory_peak_bytes": 68399104
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "baseline",
|
||||
"round": 2,
|
||||
"elapsed_ms": [
|
||||
236.412329, 219.61998900000003, 163.37286700000004, 152.177506,
|
||||
153.764226, 153.57296699999984
|
||||
],
|
||||
"result_sha256": "74eb7108ddd459dfa7bfb7a1fe653c8862eb43acd89d91ae033e7ac9158587ce",
|
||||
"wall_seconds": 1.532,
|
||||
"cpu_seconds": 1.317278,
|
||||
"memory_peak_bytes": 70189056
|
||||
},
|
||||
{
|
||||
"case": "tree-sitter-css",
|
||||
"lane": "candidate",
|
||||
"round": 2,
|
||||
"elapsed_ms": [
|
||||
15.074011000000013, 22.501490000000018, 23.890242, 9.095690999999988,
|
||||
25.85492100000002, 16.470331000000016
|
||||
],
|
||||
"result_sha256": "b59e5bdc32939c215443da6f3ce48e61fe2bfd86ff75b7a85d3c10a93b6fae7e",
|
||||
"wall_seconds": 0.524,
|
||||
"cpu_seconds": 0.297941,
|
||||
"memory_peak_bytes": 53497856
|
||||
},
|
||||
{
|
||||
"case": "tree-sitter-css",
|
||||
"lane": "baseline",
|
||||
"round": 2,
|
||||
"elapsed_ms": [
|
||||
135.69754600000002, 128.91107599999998, 115.180316, 115.23454600000002,
|
||||
117.18869600000005, 103.74374499999999
|
||||
],
|
||||
"result_sha256": "b59e5bdc32939c215443da6f3ce48e61fe2bfd86ff75b7a85d3c10a93b6fae7e",
|
||||
"wall_seconds": 1.13,
|
||||
"cpu_seconds": 0.916205,
|
||||
"memory_peak_bytes": 57880576
|
||||
},
|
||||
{
|
||||
"case": "small.decoded",
|
||||
"lane": "baseline",
|
||||
"round": 3,
|
||||
"elapsed_ms": [
|
||||
2.7721499999999963, 2.0805500000000023, 0.2946500000000043,
|
||||
0.4885200000000083, 0.37317999999999074, 1.052209999999988
|
||||
],
|
||||
"result_sha256": "beb5c7e4e8da08e3c104753b768c8ca40559d517dba80c483253991721b39c7f",
|
||||
"wall_seconds": 0.321,
|
||||
"cpu_seconds": 0.161694,
|
||||
"memory_peak_bytes": 28037120
|
||||
},
|
||||
{
|
||||
"case": "small.decoded",
|
||||
"lane": "candidate",
|
||||
"round": 3,
|
||||
"elapsed_ms": [
|
||||
2.4845909999999947, 1.5559899999999942, 1.9349599999999896,
|
||||
0.6082500000000124, 0.23478000000000065, 0.22989100000000917
|
||||
],
|
||||
"result_sha256": "beb5c7e4e8da08e3c104753b768c8ca40559d517dba80c483253991721b39c7f",
|
||||
"wall_seconds": 0.321,
|
||||
"cpu_seconds": 0.154815,
|
||||
"memory_peak_bytes": 27426816
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "baseline",
|
||||
"round": 3,
|
||||
"elapsed_ms": [
|
||||
219.92179099999998, 204.47974999999997, 159.57980799999996,
|
||||
152.3218579999999, 150.58105799999998, 149.3406970000001
|
||||
],
|
||||
"result_sha256": "74eb7108ddd459dfa7bfb7a1fe653c8862eb43acd89d91ae033e7ac9158587ce",
|
||||
"wall_seconds": 1.428,
|
||||
"cpu_seconds": 1.22534,
|
||||
"memory_peak_bytes": 71987200
|
||||
},
|
||||
{
|
||||
"case": "sqlite",
|
||||
"lane": "candidate",
|
||||
"round": 3,
|
||||
"elapsed_ms": [
|
||||
103.150995, 103.714395, 58.592934000000014, 47.94820199999998,
|
||||
47.04763299999996, 47.239012
|
||||
],
|
||||
"result_sha256": "74eb7108ddd459dfa7bfb7a1fe653c8862eb43acd89d91ae033e7ac9158587ce",
|
||||
"wall_seconds": 0.828,
|
||||
"cpu_seconds": 0.60423,
|
||||
"memory_peak_bytes": 72187904
|
||||
},
|
||||
{
|
||||
"case": "tree-sitter-css",
|
||||
"lane": "baseline",
|
||||
"round": 3,
|
||||
"elapsed_ms": [
|
||||
126.407417, 121.22317700000002, 109.654766, 108.04800599999999,
|
||||
109.459836, 100.50628600000005
|
||||
],
|
||||
"result_sha256": "b59e5bdc32939c215443da6f3ce48e61fe2bfd86ff75b7a85d3c10a93b6fae7e",
|
||||
"wall_seconds": 1.029,
|
||||
"cpu_seconds": 0.856826,
|
||||
"memory_peak_bytes": 58101760
|
||||
},
|
||||
{
|
||||
"case": "tree-sitter-css",
|
||||
"lane": "candidate",
|
||||
"round": 3,
|
||||
"elapsed_ms": [
|
||||
14.889070999999987, 15.635390999999998, 17.013621, 15.000391000000008,
|
||||
17.56236100000001, 2.893010000000004
|
||||
],
|
||||
"result_sha256": "b59e5bdc32939c215443da6f3ce48e61fe2bfd86ff75b7a85d3c10a93b6fae7e",
|
||||
"wall_seconds": 0.422,
|
||||
"cpu_seconds": 0.269288,
|
||||
"memory_peak_bytes": 57966592
|
||||
}
|
||||
],
|
||||
"limits": {
|
||||
"cpu_affinity": [15],
|
||||
"cpu_quota_percent": 100,
|
||||
"hard_memory_bytes": 4294967296,
|
||||
"early_stop_bytes": 3221225472,
|
||||
"swap_bytes": 0,
|
||||
"task_ceiling": 192
|
||||
},
|
||||
"limitations": [
|
||||
"Fresh server sessions; OS file caches warm/unflushed. Parser samples use one fresh and five repeated in-memory parses per process.",
|
||||
"SDK transport proxy counts one complete catalog plus five named request/reply envelopes. Initialization/framing and actual model usage are unmeasured. No token saving is claimed.",
|
||||
"Memory is kernel process-family memory.peak including file cache; final counters after transient scope removal remain unknown.",
|
||||
"First string-only 18-task development cohort, one invalid-source-kind harness attempt, and the cache-hit build with unverified payload cleanup are preserved outside Git and excluded from final benefit claims.",
|
||||
"Independent native WebAssembly.Module import/export oracle compiles without instantiating or executing target code. It does not prove every typed signature or unknown future proposal."
|
||||
],
|
||||
"resource_qualification": {
|
||||
"completed_mcp_tasks": 18,
|
||||
"completed_parser_processes": 18,
|
||||
"all_payload_exit_codes_zero": true,
|
||||
"all_payload_cleanup_verified": true,
|
||||
"all_payload_counters_verified": true,
|
||||
"all_memory_high_hard_oom_and_task_limit_events_zero": true,
|
||||
"final_whole_scope_counters": "unknown"
|
||||
},
|
||||
"call_sequence": [
|
||||
"inspect_wasm_artifact(summary):fresh",
|
||||
"inspect_analysis_view(exports,first4)",
|
||||
"inspect_wasm_artifact(summary):repeat",
|
||||
"inspect_analysis_view(exports,first4)",
|
||||
"export_evidence_bundle"
|
||||
],
|
||||
"transport_proxy_scope": "One complete SDK catalog and all five named request/reply envelopes, compact UTF-8 JSON encoded with cl100k_base; not actual model input."
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
# WAT framing costs on shipped WASM
|
||||
|
||||
[Issue #5760](https://github.com/morluto/rea/issues/5760) follows the current
|
||||
WASM summary workflow; no new tool, selector, cache or default is needed.
|
||||
The [curated measurements](wasm-string-framing.json) pin source, runtime,
|
||||
artifact, producer and answer fingerprints, including every final sample.
|
||||
|
||||
## Owner and preserved behavior
|
||||
|
||||
WABT's WAT framing scanned instruction text character by character. Interface
|
||||
tokenization also decoded quoted bytes merely to obtain an end position.
|
||||
`WabtString` now owns a shared quoted-string boundary operation, preserving
|
||||
escaped-quote/backslash parity. The top-level framer searches for structural
|
||||
ASCII delimiters and skips string payloads. Name and custom-payload consumers
|
||||
still decode their bytes; unsupported typed signatures remain unknown.
|
||||
Nested/line comments, exact source forms and full retained WAT remain available.
|
||||
Data forms were already excluded from interface parsing; this does not add a
|
||||
new data filter or reinterpret raw WASM outside WABT.
|
||||
|
||||
Baseline source is `d0067ba34a39`; candidate code is
|
||||
`9776d78f6c799cba8d8cf5c9b3139a86449eaebd`, based on latest main
|
||||
`335c042d166b` (the intervening main change is testing documentation).
|
||||
Linux x64, Node 24.18.0/npm 11.16.0, native WABT 1.0.42. Three alternating
|
||||
baseline/candidate, candidate/baseline, baseline/candidate pairs ran serially.
|
||||
Each task starts a fresh production stdio MCP server, discovers all 212 tools,
|
||||
inspects the selected artifact twice with existing summary delivery, reads the
|
||||
first four exact exports after each inspection, exports complete Evidence and
|
||||
closes. OS file caches are warm/unflushed; no cold-disk claim is made.
|
||||
|
||||
The public SQLite Wasm 3.53.4-build1 and VS Code tree-sitter-wasm 0.3.1 CSS
|
||||
components match the pinned [corpus](corpus.json) archive and member digests.
|
||||
An 80-byte source-assembled module supplies the small control, with an escaped
|
||||
import name. Native `WebAssembly.Module` import/export metadata independently
|
||||
checks all returned names/kinds without instantiating or executing target code.
|
||||
A separate native `wasm2wat --enable-all` output checks exact full WAT and its
|
||||
SHA-256. Every before/after original Evidence ID, normalized report digest,
|
||||
source byte digest, selected export and catalog digest agrees. This does not
|
||||
independently prove every typed signature or future WASM proposal.
|
||||
|
||||
## Completed-task costs
|
||||
|
||||
Medians of three complete tasks per side; kernel process-family memory includes
|
||||
file cache. Wall time includes startup, discovery, all five investigation RPCs,
|
||||
client validation, independent checks, export and transport cleanup.
|
||||
|
||||
| Artifact | Wall seconds, before → after | CPU seconds, before → after | Peak MiB, before → after |
|
||||
| ------------- | ---------------------------: | --------------------------: | -----------------------: |
|
||||
| Small control | 10.192 → 10.192 | 9.863 → 9.869 | 785.3 → 791.1 |
|
||||
| SQLite | 13.714 → 13.311 | 13.319 → 12.957 | 985.1 → 1149.4 |
|
||||
| CSS grammar | 12.409 → 12.112 | 12.039 → 11.727 | 1031.7 → 1071.6 |
|
||||
|
||||
Whole-task median wall reductions are about 2.9%/2.4% for SQLite/CSS; small-task
|
||||
time is unchanged. Three pairs are descriptive observations, not statistical
|
||||
or cross-provider guarantees. Memory does not improve: SQLite's median is
|
||||
higher, with overlapping 970–1141 versus 982–1156 MiB ranges. No heap-retention
|
||||
cause or memory-saving claim is established.
|
||||
|
||||
Separate fresh-process parser cohorts use one first parse and five repeated
|
||||
in-memory parses, checking the complete parsed-result digest after each parse.
|
||||
Median first/warm parse milliseconds: SQLite 236.41/153.76 → 103.56/45.54;
|
||||
CSS 133.57/111.35 → 15.07/15.64; small 2.99/0.62 → 2.49/0.40. These phase
|
||||
improvements do not include native WABT production or complete task costs.
|
||||
|
||||
The unchanged catalog and all five named request/reply envelopes cost median
|
||||
894,936 / 895,044 / 895,430 `cl100k_base` tokens for small/SQLite/CSS in both
|
||||
implementations. This is a single serialized SDK transport proxy using
|
||||
tiktoken 0.12.0; actual model input/usage, repeated model namespaces and protocol
|
||||
initialization/framing are unmeasured. No token saving is claimed.
|
||||
|
||||
All 18 final MCP tasks and 18 parser processes completed under one CPU,
|
||||
4 GiB hard/3 GiB early-stop memory, no swap and 192 tasks, with payload-exit
|
||||
counters and cleanup verified and no limit/OOM events. Final whole-scope counters
|
||||
after transient scope removal remain unknown. Raw binaries, exports,
|
||||
transcripts and logs stay outside Git. The earlier string-only 18-task
|
||||
cohort, an invalid source-kind harness attempt and a cache-hit build with
|
||||
unverified payload cleanup are retained and excluded from final benefit claims.
|
||||
|
||||
## Reproduction
|
||||
|
||||
Build/freeze each runtime with the pinned toolchain; keep the selected artifact,
|
||||
WABT directory and independently produced WAT paths identical across lanes:
|
||||
|
||||
```sh
|
||||
python3 experiments/analysis-efficiency/resource-run.py --observe-payload-exit -- \
|
||||
node experiments/analysis-efficiency/wasm-string-framing.mjs \
|
||||
--runtime /absolute/runtime --artifact /absolute/input.wasm \
|
||||
--wat /absolute/native-output.wat --tools /absolute/wabt/bin \
|
||||
--output /absolute/new-output-directory
|
||||
```
|
||||
|
||||
For parser-only cohorts, import `dist/wasm/WabtWat.js` from each frozen runtime,
|
||||
load the same native WAT once, and call `parseWabtWat(text)` six times. Measure
|
||||
each call with `performance.now()`; outside that timer, hash
|
||||
`JSON.stringify(result)` and require the same digest for every call and lane.
|
||||
Keep each artifact in a separate fresh guarded process.
|
||||
|
||||
Source verification passed 76 tests across nine files, including malformed
|
||||
strings, slash parity, comments, invalid names, capacity/partial facts,
|
||||
cancellation, cleanup retry and shared application behavior. `npm run check`
|
||||
passed typecheck, lint, formatting, Knip, metadata and architecture guards.
|
||||
Four compiled CLI/MCP/acceptance files passed another 14 tests. The native WABT
|
||||
artifact verifier passed 51 CLI/MCP cases; the native interface verifier passed
|
||||
nine cases, including all admitted kinds, escaped/BOM names, padded LEB128,
|
||||
signature changes, duplicate imports and unsupported reference semantics.
|
||||
The build used a separate 6 GiB hard/5 GiB early-stop guard; the full check used
|
||||
8/7 GiB, peaking at 5.37 GiB without resource events. These are build/check
|
||||
budgets; runtime tasks retain the smaller bounds above.
|
||||
@@ -0,0 +1,184 @@
|
||||
/** Compare unchanged public WASM tasks; raw inputs, exports and transcripts stay outside Git. */
|
||||
import assert from "node:assert/strict";
|
||||
import { createHash } from "node:crypto";
|
||||
import { createWriteStream } from "node:fs";
|
||||
import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
|
||||
import { join, resolve } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
import { finished } from "node:stream/promises";
|
||||
import { parseArgs } from "node:util";
|
||||
import { Client } from "@modelcontextprotocol/client";
|
||||
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
||||
import { createRetainedQueryCaller } from "./retained-query-calls.mjs";
|
||||
import { finalizeRetainedQueryReceipt } from "./retained-query-finalization.mjs";
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: Object.fromEntries(
|
||||
["runtime", "artifact", "wat", "tools", "output"].map((name) => [
|
||||
name,
|
||||
{ type: "string" },
|
||||
]),
|
||||
),
|
||||
});
|
||||
for (const name of ["runtime", "artifact", "wat", "tools", "output"])
|
||||
assert.ok(
|
||||
values[name] && values[name] === resolve(values[name]),
|
||||
`${name} must be absolute`,
|
||||
);
|
||||
const hash = (value) => createHash("sha256").update(value).digest("hex");
|
||||
const bytes = await readFile(values.artifact);
|
||||
const nativeWat = await readFile(values.wat, "utf8");
|
||||
// Native compilation validates the independent name inventory; no instance or target code runs.
|
||||
const module = new WebAssembly.Module(bytes);
|
||||
const nativeImports = WebAssembly.Module.imports(module);
|
||||
const nativeExports = WebAssembly.Module.exports(module);
|
||||
await mkdir(values.output, { mode: 0o700 });
|
||||
const account = await mkdtemp(join(tmpdir(), "rea-wat-framing-"));
|
||||
const client = new Client({ name: "wasm-string-framing", version: "1" });
|
||||
const transport = new StdioClientTransport({
|
||||
command: process.execPath,
|
||||
args: [join(values.runtime, "scripts/rea.mjs"), "mcp"],
|
||||
env: {
|
||||
HOME: account,
|
||||
PATH: process.env.PATH,
|
||||
NODE_OPTIONS: "--max-old-space-size=2048",
|
||||
UV_THREADPOOL_SIZE: "1",
|
||||
REA_LOG_LEVEL: "silent",
|
||||
REA_WABT_BIN_DIRECTORY: values.tools,
|
||||
TMPDIR: account,
|
||||
},
|
||||
stderr: "pipe",
|
||||
});
|
||||
const serverLog = createWriteStream(join(values.output, "server.log"));
|
||||
const serverLogFinished = finished(serverLog);
|
||||
serverLogFinished.catch(() => {});
|
||||
transport.stderr?.pipe(serverLog);
|
||||
const report = {
|
||||
artifact_sha256: hash(bytes),
|
||||
artifact_bytes: bytes.length,
|
||||
calls: [],
|
||||
answers: [],
|
||||
};
|
||||
const transcript = [];
|
||||
const call = createRetainedQueryCaller(client, (receipt, event) => {
|
||||
report.calls.push(receipt);
|
||||
transcript.push(event);
|
||||
});
|
||||
const observe = async (name, input, phase) => {
|
||||
const reply = await call(name, input, phase);
|
||||
assert.notEqual(reply.isError, true, JSON.stringify(reply));
|
||||
assert.ok(reply.structuredContent);
|
||||
return reply.structuredContent;
|
||||
};
|
||||
const started = performance.now();
|
||||
try {
|
||||
await client.connect(transport);
|
||||
const catalog = await client.listTools();
|
||||
assert.equal(catalog.nextCursor, undefined);
|
||||
await writeFile(join(values.output, "catalog.json"), JSON.stringify(catalog));
|
||||
report.catalog_sha256 = hash(JSON.stringify(catalog));
|
||||
report.catalog_tools = catalog.tools.length;
|
||||
const definitions = new Map(
|
||||
catalog.tools.map((definition) => [definition.name, definition]),
|
||||
);
|
||||
const originalCall = client.callTool.bind(client);
|
||||
client.callTool = (input, options) =>
|
||||
originalCall(input, {
|
||||
...options,
|
||||
toolDefinition: definitions.get(input.name),
|
||||
});
|
||||
const observations = [];
|
||||
for (const phase of ["fresh", "repeat"]) {
|
||||
const summary = await observe(
|
||||
"inspect_wasm_artifact",
|
||||
{ path: values.artifact, detail: "summary" },
|
||||
phase,
|
||||
);
|
||||
const parentId = summary.normalized_result.parent_evidence_id;
|
||||
const exports = await observe(
|
||||
"inspect_analysis_view",
|
||||
{
|
||||
source: { kind: "retained-evidence", evidence_id: parentId },
|
||||
view: { kind: "wasm", facet: "exports", offset: 0, limit: 4 },
|
||||
},
|
||||
`${phase}:exports`,
|
||||
);
|
||||
assert.equal(exports.normalized_result.parent_evidence_id, parentId);
|
||||
observations.push({ summary, exports, parentId });
|
||||
}
|
||||
await observe(
|
||||
"export_evidence_bundle",
|
||||
{ path: join(values.output, "evidence.json") },
|
||||
"export",
|
||||
);
|
||||
const bundle = JSON.parse(
|
||||
await readFile(join(values.output, "evidence.json"), "utf8"),
|
||||
);
|
||||
const kind = (value) => (value === "func" ? "function" : value);
|
||||
for (const { summary, exports, parentId } of observations) {
|
||||
const parent = bundle.records.find(
|
||||
(record) => record.evidence_id === parentId,
|
||||
);
|
||||
assert.ok(parent);
|
||||
assert.equal(parent.subject.digest.sha256, report.artifact_sha256);
|
||||
const facts = parent.normalized_result;
|
||||
assert.equal(facts.validation, "valid");
|
||||
assert.equal(facts.wat.text, nativeWat);
|
||||
assert.equal(facts.wat.sha256, hash(nativeWat));
|
||||
assert.equal(facts.interface.state, "complete");
|
||||
assert.deepEqual(
|
||||
facts.interface.entries
|
||||
.filter((entry) => entry.direction === "import")
|
||||
.map((entry) => ({
|
||||
module: entry.module,
|
||||
name: entry.name,
|
||||
kind: kind(entry.kind),
|
||||
})),
|
||||
nativeImports,
|
||||
);
|
||||
assert.deepEqual(
|
||||
facts.interface.entries
|
||||
.filter((entry) => entry.direction === "export")
|
||||
.map((entry) => ({ name: entry.name, kind: kind(entry.kind) })),
|
||||
nativeExports,
|
||||
);
|
||||
assert.deepEqual(exports.normalized_result.item, facts.exports.slice(0, 4));
|
||||
assert.equal(
|
||||
summary.normalized_result.summary.available_counts.imports,
|
||||
nativeImports.length,
|
||||
);
|
||||
assert.equal(
|
||||
summary.normalized_result.summary.available_counts.exports,
|
||||
nativeExports.length,
|
||||
);
|
||||
assert.equal(facts.runtime_execution, "not-performed");
|
||||
assert.equal(facts.network_fetch, "not-performed");
|
||||
report.answers.push({
|
||||
parent_evidence_id: parentId,
|
||||
normalized_sha256: hash(JSON.stringify(facts)),
|
||||
exports: exports.normalized_result.item,
|
||||
});
|
||||
}
|
||||
assert.deepEqual(report.answers[0], report.answers[1]);
|
||||
assert.equal(hash(await readFile(values.artifact)), report.artifact_sha256);
|
||||
report.status = "passed";
|
||||
} catch (cause) {
|
||||
report.status = "failed";
|
||||
report.failure = String(cause?.stack ?? cause);
|
||||
process.exitCode = 1;
|
||||
} finally {
|
||||
report.elapsed_ms_before_cleanup = performance.now() - started;
|
||||
if (
|
||||
!(await finalizeRetainedQueryReceipt({
|
||||
report,
|
||||
client,
|
||||
transport,
|
||||
account,
|
||||
serverLog,
|
||||
serverLogFinished,
|
||||
output: values.output,
|
||||
transcript,
|
||||
}))
|
||||
)
|
||||
process.exitCode = 1;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import type {
|
||||
WasmInterfaceSignature,
|
||||
WasmInterfaceValueType,
|
||||
} from "../domain/wasm/wasmInterface.js";
|
||||
import { watString } from "./WabtString.js";
|
||||
import { watString, watStringEnd } from "./WabtString.js";
|
||||
|
||||
/** Split direct WAT children only; function instruction bodies are never materialized. */
|
||||
const parts = (form: string): string[] => {
|
||||
@@ -40,12 +40,12 @@ const parts = (form: string): string[] => {
|
||||
}
|
||||
const start = i;
|
||||
if (form[i] === '"') {
|
||||
i = watString(form, i + 1).end;
|
||||
i = watStringEnd(form, i + 1);
|
||||
} else if (form[i] === "(") {
|
||||
let depth = 1;
|
||||
i++;
|
||||
while (i < form.length && depth > 0) {
|
||||
if (form[i] === '"') i = watString(form, i + 1).end;
|
||||
if (form[i] === '"') i = watStringEnd(form, i + 1);
|
||||
else {
|
||||
if (form[i] === "(") depth++;
|
||||
else if (form[i] === ")") depth--;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { expect, it } from "vitest";
|
||||
import { parseWabtWat } from "./WabtWat.js";
|
||||
import { watString, watStringEnd } from "./WabtString.js";
|
||||
|
||||
it("frames escaped quotes and trailing backslashes without consuming the next form", () => {
|
||||
const source = String.raw`prefix "a\"b\\" (export "next" (func 0))`;
|
||||
const end = source.indexOf(" (export");
|
||||
expect(watStringEnd(source, 8)).toBe(end);
|
||||
expect(watString(source, 8)).toEqual({
|
||||
bytes: Buffer.from('a"b\\'),
|
||||
end,
|
||||
});
|
||||
expect(watStringEnd('""', 1)).toBe(2);
|
||||
for (const count of [1, 2, 3, 4, 5]) {
|
||||
for (const tail of ['"tail', ""]) {
|
||||
const value = "\\".repeat(count) + tail;
|
||||
const encoded = JSON.stringify(value);
|
||||
const source = encoded + ' (export "next" (func 0))';
|
||||
expect(watStringEnd(source, 1)).toBe(encoded.length);
|
||||
expect(watString(source, 1).bytes).toEqual(Buffer.from(value));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects missing terminators, including a dangling escape or escaped last quote", () => {
|
||||
for (const source of ['"', '"payload', '"payload\\', '"payload\\"']) {
|
||||
expect(() => watStringEnd(source, 1)).toThrow("Incomplete WABT string");
|
||||
expect(() => watString(source, 1)).toThrow("Incomplete WABT string");
|
||||
expect(() => parseWabtWat(`(module (import ${source}`)).toThrow();
|
||||
}
|
||||
});
|
||||
|
||||
it("preserves quoted WAT punctuation, nested comments, escaped names and unknown signatures", () => {
|
||||
const result = parseWabtWat(String.raw`(module
|
||||
(; outer " (; inner ;) ;)
|
||||
(import "env" "a\"b\\(;);;\00" (func (param i32)))
|
||||
(memory 1 (future-proposal "ignored\ff"))
|
||||
(export "memory" (memory 0))
|
||||
(data (i32.const 0) "(; );) ;; \" \\"))`);
|
||||
expect(result.interface.entries).toMatchObject([
|
||||
{
|
||||
direction: "import",
|
||||
name: 'a"b\\(;);;\0',
|
||||
signature: { kind: "func", params: ["i32"] },
|
||||
},
|
||||
{
|
||||
direction: "export",
|
||||
name: "memory",
|
||||
signature: null,
|
||||
issue: expect.any(String),
|
||||
},
|
||||
]);
|
||||
expect(() => parseWabtWat('(module (import "env" "\\q" (func)))')).toThrow(
|
||||
"Unsupported WABT name escape",
|
||||
);
|
||||
});
|
||||
+18
-10
@@ -1,13 +1,21 @@
|
||||
/** Decode a producer WAT string to frame objdump's raw display text. */
|
||||
export const watString = (form: string, start: number) => {
|
||||
let end = start;
|
||||
while (end < form.length && form[end] !== '"') {
|
||||
if (form[end] === "\\") end++;
|
||||
end++;
|
||||
/** Locate a WAT string's exclusive end without decoding or copying its payload. */
|
||||
export const watStringEnd = (form: string, start: number): number => {
|
||||
for (
|
||||
let end = form.indexOf('"', start);
|
||||
end !== -1;
|
||||
end = form.indexOf('"', end + 1)
|
||||
) {
|
||||
let escapes = end;
|
||||
while (escapes > start && form[escapes - 1] === "\\") escapes--;
|
||||
if ((end - escapes) % 2 === 0) return end + 1;
|
||||
}
|
||||
if (end === form.length)
|
||||
throw new Error("Incomplete WABT custom-section name.");
|
||||
const name = form.slice(start, end);
|
||||
throw new Error("Incomplete WABT string.");
|
||||
};
|
||||
|
||||
/** Decode a producer WAT string only where its bytes are interpreted. */
|
||||
export const watString = (form: string, start: number) => {
|
||||
const end = watStringEnd(form, start);
|
||||
const name = form.slice(start, end - 1);
|
||||
// Escapes shrink; literal UTF-8 has the same byte extent as its source.
|
||||
const bytes = Buffer.alloc(Buffer.byteLength(name, "utf8"));
|
||||
let length = 0;
|
||||
@@ -42,5 +50,5 @@ export const watString = (form: string, start: number) => {
|
||||
index += 2;
|
||||
}
|
||||
}
|
||||
return { bytes: bytes.subarray(0, length), end: end + 1 };
|
||||
return { bytes: bytes.subarray(0, length), end };
|
||||
};
|
||||
+11
-9
@@ -1,5 +1,5 @@
|
||||
import { parseWabtInterface } from "./WabtInterface.js";
|
||||
import { watString } from "./WabtString.js";
|
||||
import { watString, watStringEnd } from "./WabtString.js";
|
||||
|
||||
/** Read only module-name metadata from WABT's preserved name-section payload. */
|
||||
const moduleNames = (bytes: Uint8Array): string[] => {
|
||||
@@ -48,22 +48,24 @@ export const parseWabtWat = (text: string) => {
|
||||
const debugModuleNames: string[] = [];
|
||||
let depth = 0;
|
||||
let start = 0;
|
||||
let quoted = false;
|
||||
let commentDepth = 0;
|
||||
let lineComment = false;
|
||||
let closed = false;
|
||||
const boundaries = /[()";]/gu;
|
||||
for (let index = 0; index < text.length; index++) {
|
||||
// Instructions and whitespace inside a form cannot change its framing.
|
||||
if (depth > 0 && !lineComment && commentDepth === 0) {
|
||||
boundaries.lastIndex = index;
|
||||
const boundary = boundaries.exec(text);
|
||||
if (boundary === null) break;
|
||||
index = boundary.index;
|
||||
}
|
||||
const char = text[index];
|
||||
const next = text[index + 1];
|
||||
if (lineComment) {
|
||||
if (char === "\n") lineComment = false;
|
||||
continue;
|
||||
}
|
||||
if (quoted) {
|
||||
if (char === "\\") index++;
|
||||
else if (char === '"') quoted = false;
|
||||
continue;
|
||||
}
|
||||
if (commentDepth > 0) {
|
||||
if (char === "(" && next === ";") {
|
||||
commentDepth++;
|
||||
@@ -87,7 +89,7 @@ export const parseWabtWat = (text: string) => {
|
||||
if (char === '"') {
|
||||
if (depth === 0)
|
||||
throw new Error("Unexpected string outside WABT WAT module.");
|
||||
quoted = true;
|
||||
index = watStringEnd(text, index + 1) - 1;
|
||||
continue;
|
||||
}
|
||||
if (char === "(") {
|
||||
@@ -133,7 +135,7 @@ export const parseWabtWat = (text: string) => {
|
||||
} else if (depth === 0 && char !== undefined && !/\s/u.test(char))
|
||||
throw new Error("Unexpected text outside WABT WAT module.");
|
||||
}
|
||||
if (depth !== 0 || quoted || commentDepth !== 0)
|
||||
if (depth !== 0 || commentDepth !== 0)
|
||||
throw new Error("Incomplete WABT WAT output.");
|
||||
return {
|
||||
imports,
|
||||
|
||||
Reference in new issue
Block a user