Skip to content

fix(json): JSON.parse<T> with 'any'-typed field stores raw JSON substring#555

Merged
cs01 merged 1 commit intomainfrom
fix/json-any-field-passthrough
Apr 19, 2026
Merged

fix(json): JSON.parse<T> with 'any'-typed field stores raw JSON substring#555
cs01 merged 1 commit intomainfrom
fix/json-any-field-passthrough

Conversation

@cs01
Copy link
Copy Markdown
Owner

@cs01 cs01 commented Apr 19, 2026

Summary

Closes dapweb NOTES #12. any-typed fields inside a JSON.parse interface previously emitted @parse_json_any — broken IR with 'use of undefined type named any'. Now the parser serializes the JSON value's source text back to a string via csyyjson_val_write and stores it in the struct slot as i8*.

Why this is useful, not a hack

This is exactly the semantics for polymorphic payload dispatch (DAP, JSON-RPC, webhooks):

interface Envelope { command: string; body: any; }
const e = JSON.parse<Envelope>(rawWire);
switch (e.command) {
  case "launch": {
    const args = JSON.parse<LaunchArgs>(e.body);  // re-parse raw substring
    runLaunch(args);
    break;
  }
  case "setBreakpoints": {
    const args = JSON.parse<SetBreakpointsArgs>(e.body);
    ...
  }
}

dapweb was doing this manually with an extractField() walker — now it's native, zero boilerplate.

Scope note

any remains rejected as a parameter type (#5 behavior unchanged). This PR only addresses the interface-field case, where the field type maps to i8* anyway — the parser was just missing the generation branch.

Test plan

  • New fixture tests/fixtures/builtins/json-parse-any-field.ts covers full envelope-dispatch pattern
  • CI green

…ring

previously `any`-typed field in a typed-parse interface emitted
`call %any* @parse_json_any(i8* ...)` — broken IR ('use of undefined
type named any').

fix: parse writes the field's JSON source text back to a string via
csyyjson_val_write and stores it in the struct slot as i8*. users can
then re-parse the substring with JSON.parse<ConcreteShape>(field) once
they know the shape from a sibling discriminant ('command', 'method',
event type, etc.).

concretely enables the envelope pattern dapweb was forced to implement
manually via an extractField walker:

  interface Envelope { command: string; body: any; }
  const e = JSON.parse<Envelope>(rawWire);
  switch (e.command) {
    case "launch":
      const a = JSON.parse<LaunchArgs>(e.body);
      ...
  }

closes dapweb NOTES #12.
@github-actions
Copy link
Copy Markdown
Contributor

Benchmark Results (Linux x86-64)

Benchmark C ChadScript Go Node Place
Binary Trees 1.335s 1.215s 2.695s 1.139s 🥈
Cold Start 0.9ms 0.8ms 1.2ms 25.5ms 🥇
Fibonacci 0.815s 0.680s 1.572s 3.189s 🥇
File I/O 0.118s 0.099s 0.086s 0.202s 🥈
JSON Parse/Stringify 0.004s 0.005s 0.017s 0.014s 🥈
Matrix Multiply 0.448s 0.686s 0.557s 0.371s #4
Monte Carlo Pi 0.388s 0.410s 0.405s 2.248s 🥉
N-Body Simulation 1.671s 2.118s 2.196s 2.387s 🥈
Quicksort 0.215s 0.244s 0.212s 0.261s 🥉
SQLite 0.354s 0.367s 0.415s 🥈
Sieve of Eratosthenes 0.013s 0.024s 0.018s 0.038s 🥉
String Manipulation 0.008s 0.018s 0.017s 0.036s 🥉

CLI Tool Benchmarks

Benchmark ChadScript grep node xxd Place
Hex Dump 0.564s 0.952s 0.129s 🥈
Recursive Grep 0.019s 0.009s 0.099s 🥈

@cs01 cs01 merged commit cda3584 into main Apr 19, 2026
10 of 12 checks passed
@cs01 cs01 deleted the fix/json-any-field-passthrough branch April 24, 2026 20:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant