@@ -99,9 +99,9 @@ module Line_writer : sig
9999
100100 val of_channel : out_channel -> t
101101
102- val write : ?source : Line_reader .t -> t -> string -> unit
102+ val write : ?source : Line_reader .t -> t -> string -> int
103103
104- val write_lines : ?source : Line_reader .t -> t -> string -> unit
104+ val write_lines : ?source : Line_reader .t -> t -> string -> int
105105
106106 val lnum : t -> int
107107end = struct
@@ -134,17 +134,20 @@ end = struct
134134 output_string t.oc " \n " ;
135135 let lnum_off = lnum_off + 1 in
136136 t.source < - source;
137- t.lnum < - t.lnum + lnum_off
137+ t.lnum < - t.lnum + lnum_off;
138+ lnum_off
138139
139140 let write_lines ?source t lines =
141+ let lnum = t.lnum in
140142 let l = String. split_on_char ~sep: '\n' lines in
141143 let rec w = function
142144 | [ " " ] | [] -> ()
143145 | s :: xs ->
144- write ?source t s;
146+ let _ = write ?source t s in
145147 w xs
146148 in
147- w l
149+ w l;
150+ t.lnum - lnum
148151
149152 let lnum t = t.lnum
150153end
@@ -318,12 +321,26 @@ let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source
318321 in
319322 let sm_for_file = ref None in
320323 let ic = Line_reader. open_ file in
321- let skip ic = Line_reader. drop ic in
322- let reloc = ref [] in
324+ let old_line_count = Line_writer. lnum oc in
325+ let edits = ref [] in
326+ let skip ic =
327+ edits := Source_map.Line_edits. Drop :: ! edits;
328+ Line_reader. drop ic
329+ in
323330 let copy ic oc =
324331 let line = Line_reader. next ic in
325- Line_writer. write ~source: ic oc line;
326- reloc := (Line_reader. lnum ic, Line_writer. lnum oc) :: ! reloc
332+ let count = Line_writer. write ~source: ic oc line in
333+ if count > 1
334+ then edits := Source_map.Line_edits. Add { count = count - 1 } :: ! edits;
335+ edits := Source_map.Line_edits. Keep :: ! edits
336+ in
337+ let write_line oc str =
338+ let count = Line_writer. write oc str in
339+ edits := Source_map.Line_edits. (Add { count }) :: ! edits
340+ in
341+ let write_lines oc str =
342+ let count = Line_writer. write_lines oc str in
343+ edits := Source_map.Line_edits. (Add { count }) :: ! edits
327344 in
328345 let rec read () =
329346 match Line_reader. peek ic with
@@ -342,7 +359,7 @@ let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source
342359 if not ! build_info_emitted
343360 then (
344361 let bi = Build_info. with_kind bi (if mklib then `Cma else `Unknown ) in
345- Line_writer. write_lines oc (Build_info. to_string bi);
362+ write_lines oc (Build_info. to_string bi);
346363 build_info_emitted := true )
347364 | Drop -> skip ic
348365 | Unit ->
@@ -358,7 +375,7 @@ let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source
358375 (if mklib
359376 then
360377 let u = if linkall then { u with force_link = true } else u in
361- Line_writer. write_lines oc (Unit_info. to_string u));
378+ write_lines oc (Unit_info. to_string u));
362379 let size = ref 0 in
363380 while
364381 match Line_reader. peek ic with
@@ -402,7 +419,7 @@ let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source
402419 read ()
403420 in
404421 read () ;
405- Line_writer. write oc " " ;
422+ write_line oc " " ;
406423 Line_reader. close ic;
407424 (match is_runtime with
408425 | None -> ()
@@ -424,10 +441,10 @@ let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source
424441 (Parse_bytecode.Debug. create ~include_cmis: false false )
425442 code;
426443 let content = Buffer. contents b in
427- Line_writer. write_lines oc content);
444+ write_lines oc content);
428445 (match ! sm_for_file with
429446 | None -> ()
430- | Some x -> sm := (x, ! reloc ) :: ! sm);
447+ | Some x -> sm := (x, List. rev ! edits, Line_writer. lnum oc - old_line_count ) :: ! sm);
431448 match ! build_info, build_info_for_file with
432449 | None , None -> ()
433450 | Some _ , None -> ()
@@ -440,32 +457,55 @@ let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source
440457 match source_map with
441458 | None -> ()
442459 | Some (file , init_sm ) ->
443- let sm =
444- List. rev_map ! sm ~f: (fun (sm , reloc ) ->
445- let tbl = Hashtbl. create 17 in
446- List. iter reloc ~f: (fun (a , b ) -> Hashtbl. add tbl a b);
447- Source_map. filter_map sm ~f: (Hashtbl. find_opt tbl))
460+ let sourcemaps_and_line_counts =
461+ List. rev_map ! sm ~f: (fun (sm , edits , lcount ) ->
462+ (*
463+ (match file with
464+ | Some f -> Format.eprintf "file = %s@," f
465+ | None -> ());
466+ Format.eprintf "@[<v 2>edits =@ %a@,@]" Source_map.Line_edits.pp edits;
467+ *)
468+ let mappings = sm.Source_map. mappings in
469+ (*
470+ Format.eprintf "mappings = %s@," sm.Source_map.mappings;
471+ *)
472+ let mappings = Source_map.Mappings. edit ~strict: false mappings edits in
473+ { sm with mappings }, lcount)
448474 in
449- (match Source_map. merge (init_sm :: sm) with
450- | None -> ()
451- | Some sm -> (
452- (* preserve some info from [init_sm] *)
453- let sm =
454- { sm with
455- version = init_sm.version
456- ; file = init_sm.file
457- ; sourceroot = init_sm.sourceroot
458- }
459- in
460- match file with
461- | None ->
462- let data = Source_map_io. to_string sm in
463- let s = sourceMappingURL_base64 ^ Base64. encode_exn data in
464- Line_writer. write oc s
465- | Some file ->
466- Source_map_io. to_file sm file;
467- let s = sourceMappingURL ^ Filename. basename file in
468- Line_writer. write oc s));
475+ let merged_sourcemap =
476+ let open Source_map in
477+ assert (match init_sm.mappings with Uninterpreted "" -> true | _ -> false );
478+ { version = init_sm.version
479+ ; file = init_sm.file
480+ ; Composite. sections =
481+ (let _, sections =
482+ List. fold_right
483+ sourcemaps_and_line_counts
484+ ~f: (fun (sm , generated_line_count ) (cur_ofs , sections ) ->
485+ let offset = Composite. { gen_line = cur_ofs; gen_column = 0 } in
486+ cur_ofs + generated_line_count, (offset, `Map sm) :: sections)
487+ ~init: (0 , [] )
488+ in
489+ List. rev sections)
490+ }
491+ in
492+ (* preserve some info from [init_sm] *)
493+ let merged_sourcemap =
494+ { merged_sourcemap with
495+ sections =
496+ List. map merged_sourcemap.sections ~f: (fun (ofs , `Map sm ) ->
497+ ofs, `Map { sm with sourceroot = init_sm.sourceroot })
498+ }
499+ in
500+ (match file with
501+ | None ->
502+ let data = Source_map_io.Composite. to_string merged_sourcemap in
503+ let s = sourceMappingURL_base64 ^ Base64. encode_exn data in
504+ Line_writer. write oc s |> ignore
505+ | Some file ->
506+ Source_map_io.Composite. to_file merged_sourcemap file;
507+ let s = sourceMappingURL ^ Filename. basename file in
508+ Line_writer. write oc s |> ignore);
469509 if times () then Format. eprintf " sourcemap: %a@." Timer. print t
470510
471511let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source_map =
0 commit comments