mirage / ezjsonm

An easy interface on top of the Jsonm library.
Other
40 stars 22 forks source link

Stack-overflow in json_of_src when built with JSOO (with potential fix) #41

Closed smondet closed 3 years ago

smondet commented 4 years ago

AFAIK JSOO optimizes only self-tail-calls so Ezjsonm.value_from_string fails on biggish values with stack-overflow (at least at 20 KB json for me on chrome & firefox)

I have an imperative implementation here that fixes the problem for my case (one self-tail-call actually): https://github.com/tqtezos/TZComet/pull/8/files

It's way longer & messier, and could have some subtle bug I haven't hit yet. And fixes a problem only in the JSOO case.

Is a PR for this something that you'd be interested in?

dinosaure commented 4 years ago

It can be interesting yes to integrate it into the distribution :+1:. I'm wondering about performances on the native compilation and if we can orchestrate your implementation only when we want to compile with js_of_ocaml. The better is to propose a PR and we will refine it then 🙂 .

smondet commented 3 years ago

@dinosaure & @gasche I hit the opposite problem: stack-overflow while serializing a big JSON value, I replaced json_to_dst with a self-tail-call one also:

    let value_to_dst ?(minify = true) dst json =
      let encoder = Jsonm.encoder ~minify dst in
      let encode l = ignore (Jsonm.encode encoder (`Lexeme l)) in
      let rec go = function
        | [] -> ()
        | `Value ((`Bool _ | `Null | `Float _ | `String _) as v) :: more ->
            encode v ; go more
        | `Value (`O l) :: more ->
            encode `Os ;
            go (`Object l :: more)
        | `Value (`A l) :: more ->
            encode `As ;
            go (`Array l :: more)
        | `Object [] :: more ->
            encode `Oe ;
            go more
        | `Object ((k, v) :: o) :: more ->
            encode (`Name k) ;
            go (`Value v :: `Object o :: more)
        | `Array [] :: more ->
            encode `Ae ;
            go more
        | `Array (v :: aa) :: more -> go (`Value v :: `Array aa :: more) in
      go [`Value json] ;
      ignore (Jsonm.encode encoder `End)