File: dump_sourcemap.ml

package info (click to toggle)
js-of-ocaml 5.9.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 32,020 kB
  • sloc: ml: 91,250; javascript: 57,289; ansic: 315; makefile: 271; lisp: 23; sh: 6; perl: 4
file content (98 lines) | stat: -rw-r--r-- 3,003 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
open Js_of_ocaml_compiler
open Stdlib

let normalize_path s =
  let s =
    String.map
      ~f:(function
        | '\\' -> '/' (* Normalize windows path for the tests *)
        | x -> x)
      s
  in
  Filename.basename s

let input_lines file =
  let rec loop acc ic =
    match input_line ic with
    | line -> loop (line :: acc) ic
    | exception End_of_file -> List.rev acc
  in
  let ic = open_in file in
  let lines = loop [] ic in
  close_in ic;
  lines

let extract_sourcemap lines =
  let lines =
    List.filter_map lines ~f:(String.drop_prefix ~prefix:"//# sourceMappingURL=")
  in
  match lines with
  | [ line ] ->
      let content =
        match String.drop_prefix ~prefix:"data:application/json;base64," line with
        | None -> String.concat ~sep:"\n" (input_lines line)
        | Some base64 -> Base64.decode_exn base64
      in
      Some (Source_map.of_string content)
  | _ -> None

let print_mapping lines ?(line_offset = 0) (sm : Source_map.Standard.t) =
  let lines = Array.of_list lines in
  let sources = Array.of_list sm.sources in
  let _names = Array.of_list sm.names in
  let mappings = Source_map.Mappings.decode_exn sm.mappings in
  List.iter mappings ~f:(fun (m : Source_map.map) ->
      let file = function
        | -1 -> "null"
        | n -> normalize_path sources.(n)
      in
      let mark col line =
        let len = String.length line in
        if col > len
        then line ^ String.init (col - len) ~f:(fun _ -> ' ') ^ "<>"
        else
          String.sub line ~pos:0 ~len:col
          ^ "<>"
          ^ String.sub line ~pos:col ~len:(len - col)
      in
      match m with
      | Gen _ -> ()
      | Gen_Ori { gen_line; gen_col; ori_line; ori_col; ori_source }
      | Gen_Ori_Name { gen_line; gen_col; ori_line; ori_col; ori_source; ori_name = _ }
        -> (
          match file ori_source with
          | "a.ml" | "b.ml" | "c.ml" | "d.ml" ->
              let root =
                match sm.sourceroot with
                | None -> ""
                | Some root -> root ^ "#"
              in
              Printf.printf
                "%s%s:%d:%d -> %d:%s\n"
                root
                (file ori_source)
                ori_line
                ori_col
                gen_col
                (mark gen_col lines.(gen_line - 1 + line_offset))
          | _ -> ()))

let print_sourcemap lines = function
  | Source_map.Standard sm -> print_mapping lines sm
  | Index l ->
      List.iter
        l.Source_map.Index.sections
        ~f:(fun { Source_map.Index.offset = { gen_line; gen_column }; map } ->
          assert (gen_column = 0);
          print_mapping lines ~line_offset:gen_line map)

let files = Sys.argv |> Array.to_list |> List.tl

let () =
  List.iter files ~f:(fun f ->
      let lines = input_lines f in
      match extract_sourcemap lines with
      | None -> Printf.printf "not sourcemap for %s\n" f
      | Some sm ->
          Printf.printf "sourcemap for %s\n" f;
          print_sourcemap lines sm)