From 4494d81f8cf6faecf5ff43c0d1e69cd8777c5f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Vouillon?= Date: Thu, 17 Oct 2024 17:46:54 +0200 Subject: [PATCH] Source map: repeat mappings over new lines Firefox assumes that a mapping stops at the end of a line, which is inconvenient. When this happens, we repeat the mapping on the next line. --- compiler/lib/js_output.ml | 53 ++++++++++++++++++------- compiler/tests-compiler/sourcemap.ml | 2 + compiler/tests-sourcemap/dump.reference | 1 + 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/compiler/lib/js_output.ml b/compiler/lib/js_output.ml index 8cd987b758..cea059b47e 100644 --- a/compiler/lib/js_output.ml +++ b/compiler/lib/js_output.ml @@ -2154,22 +2154,45 @@ let program ?(accept_unnamed_var = false) f ?source_map p = String.length filename >= 9 && String.sub filename 0 9 = "/builtin/") in let sm_mappings = Source_map.Mappings.decode sm.mappings in - let mappings = - List.rev_append_map !temp_mappings sm_mappings ~f:(fun (pos, m) -> - let gen_line = pos.PP.p_line + 1 in - let gen_col = pos.PP.p_col in - match m with - | Source_map.Gen { gen_col = _; gen_line = _ } -> - Source_map.Gen { gen_col; gen_line } - | Source_map.Gen_Ori - { gen_line = _; gen_col = _; ori_source; ori_line; ori_col } -> - Source_map.Gen_Ori { gen_line; gen_col; ori_source; ori_line; ori_col } - | Source_map.Gen_Ori_Name - { gen_line = _; gen_col = _; ori_source; ori_line; ori_col; ori_name } - -> - Source_map.Gen_Ori_Name - { gen_line; gen_col; ori_source; ori_line; ori_col; ori_name }) + let relocate pos m = + let gen_line = pos.PP.p_line + 1 in + let gen_col = pos.PP.p_col in + match m with + | Source_map.Gen { gen_col = _; gen_line = _ } -> + Source_map.Gen { gen_col; gen_line } + | Source_map.Gen_Ori m -> Source_map.Gen_Ori { m with gen_line; gen_col } + | Source_map.Gen_Ori_Name m -> + Source_map.Gen_Ori_Name { m with gen_line; gen_col } + in + let prepend mapping prev_mappings = + let rec prepend_rec pos mapping prev_mappings = + match mapping with + | [] -> prev_mappings + | (pos', m) :: rem -> + (* + Format.eprintf + "%d,%d %d,%d@." + pos'.PP.p_line + pos'.PP.p_col + pos.PP.p_line + pos.PP.p_col; +*) + if pos'.PP.p_line = pos.PP.p_line + || (pos'.p_line = pos.p_line - 1 && pos.p_col = 0) + then prepend_rec pos' rem (relocate pos' m :: prev_mappings) + else if pos.p_col > 0 + then + let pos = { pos with p_col = 0 } in + prepend_rec pos mapping (relocate pos m :: prev_mappings) + else + let pos = { pos with p_line = pos.p_line - 1 } in + prepend_rec pos mapping (relocate pos m :: prev_mappings) + in + match mapping with + | [] -> prev_mappings + | (pos, m) :: rem -> prepend_rec pos rem (relocate pos m :: prev_mappings) in + let mappings = prepend !temp_mappings sm_mappings in let mappings = Source_map.Mappings.encode mappings in Some { sm with diff --git a/compiler/tests-compiler/sourcemap.ml b/compiler/tests-compiler/sourcemap.ml index 4cbcbb09d2..2204eb5ca5 100644 --- a/compiler/tests-compiler/sourcemap.ml +++ b/compiler/tests-compiler/sourcemap.ml @@ -84,10 +84,12 @@ let%expect_test _ = 13: //# sourceMappingURL=test.map /builtin/blackbox.ml:1:0 -> 5:7 /builtin/blackbox.ml:1:0 -> 5:17 + /builtin/blackbox.ml:1:0 -> 6:0 /dune-root/test.ml:1:4 -> 6:12 /dune-root/test.ml:1:7 -> 6:15 /dune-root/test.ml:1:11 -> 6:18 /dune-root/test.ml:1:12 -> 6:28 + /dune-root/test.ml:1:12 -> 7:0 /dune-root/test.ml:1:12 -> 7:7 /builtin/blackbox.ml:1:0 -> 7:14 |}] diff --git a/compiler/tests-sourcemap/dump.reference b/compiler/tests-sourcemap/dump.reference index 5feb760f7e..ca2f059261 100644 --- a/compiler/tests-sourcemap/dump.reference +++ b/compiler/tests-sourcemap/dump.reference @@ -3,4 +3,5 @@ sourcemap for test.bc.js /my/sourceRoot#b.ml:1:6 -> 14: function f(<>x){return x - 1 | 0; } /my/sourceRoot#b.ml:1:10 -> 17: function f(x){<>return x - 1 | 0; } /my/sourceRoot#b.ml:1:15 -> 35: function f(x){return x - 1 | 0; <>} +/my/sourceRoot#b.ml:1:15 -> 0:<> var Testlib_B = [0, f]; /my/sourceRoot#b.ml:1:15 -> 7: var <>Testlib_B = [0, f];