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)
|