@@ -256,16 +256,29 @@ module Mappings = struct
256256 ; ori_col = ! ori_col
257257 ; ori_name = ! ori_name
258258 }
259- | _ -> invalid_arg " Source_map.mapping_of_string "
259+ | _ -> invalid_arg " Source_map.Mappings.decode_exn "
260260 in
261261 let acc = v :: acc in
262262 if last = stop then last + 1 , acc else read_tokens line (last + 1 ) stop acc
263263 in
264264 (* The binary format encodes lines starting at zero, but
265265 [ori_line] and [gen_line] are 1 based. *)
266266 readline 1 0 []
267+
268+ let invariant ~names :_ ~sources :_ (Uninterpreted str ) =
269+ (* We can't check much without decoding (which is expensive) *)
270+ (* Just do very simple checks *)
271+ if not
272+ (String. for_all str ~f: (function
273+ | ';' | ',' -> true
274+ | x -> Vlq64. in_alphabet x))
275+ then invalid_arg " Mappings.invariant"
267276end
268277
278+ let version_is_valid = function
279+ | 3 -> true
280+ | _ -> false
281+
269282let rewrite_path path =
270283 if Filename. is_relative path
271284 then path
@@ -463,7 +476,8 @@ module Standard = struct
463476
464477 let of_json (json : Yojson.Raw.t ) =
465478 match json with
466- | `Assoc (("version" , `Intlit version ) :: rest ) when int_of_string version = 3 ->
479+ | `Assoc ((" version" , `Intlit version) :: rest)
480+ when version_is_valid (int_of_string version) ->
467481 let string name json = Option. map ~f: string_of_stringlit (stringlit name json) in
468482 let file = string " file" rest in
469483 let sourceroot = string " sourceRoot" rest in
@@ -491,7 +505,7 @@ module Standard = struct
491505 | None -> Mappings. empty
492506 | Some s -> Mappings. of_string_unsafe s
493507 in
494- { version = int_of_float (float_of_string version)
508+ { version = int_of_string version
495509 ; file
496510 ; sourceroot
497511 ; names
@@ -504,8 +518,21 @@ module Standard = struct
504518 let to_string m = Yojson.Raw. to_string (json m)
505519
506520 let to_file m file = Yojson.Raw. to_file file (json m)
521+
522+ let invariant
523+ { version; file = _ ; sourceroot = _ ; names; sources_content; sources; mappings } =
524+ if not (version_is_valid version)
525+ then invalid_arg " Source_map.Standard.invariant: invalid version" ;
526+ match sources_content with
527+ | None -> ()
528+ | Some x ->
529+ if not (List. length sources = List. length x)
530+ then
531+ invalid_arg
532+ " Source_map.Standard.invariant: sources and sourcesContent must have the \
533+ same size" ;
534+ Mappings. invariant ~names ~sources mappings
507535end
508- (* IO *)
509536
510537module Index = struct
511538 type section =
@@ -564,52 +591,70 @@ module Index = struct
564591 " line"
565592 fields
566593 ~errmsg:
567- " Source_map_io .Index.of_json: field 'line' absent or invalid from \
594+ " Source_map .Index.of_json: field 'line' absent or invalid from \
568595 section"
569596 in
570597 let gen_column =
571598 intlit
572599 " column"
573600 fields
574601 ~errmsg:
575- " Source_map_io .Index.of_json: field 'column' absent or invalid from \
602+ " Source_map .Index.of_json: field 'column' absent or invalid from \
576603 section"
577604 in
578605 { Offset. gen_line; gen_column }
579- | _ ->
580- invalid_arg " Source_map_io.Index.of_json: 'offset' field of unexpected type"
606+ | _ -> invalid_arg " Source_map.Index.of_json: 'offset' field of unexpected type"
581607 in
582608 (match List. assoc " url" json with
583609 | _ ->
584610 invalid_arg
585- " Source_map_io.Index.of_json: URLs in index maps are not currently \
586- supported"
611+ " Source_map.Index.of_json: URLs in index maps are not currently supported"
587612 | exception Not_found -> () );
588613 let map =
589614 try Standard. of_json (List. assoc " map" json) with
590- | Not_found -> invalid_arg " Source_map_io .Index.of_json: field 'map' absent"
615+ | Not_found -> invalid_arg " Source_map .Index.of_json: field 'map' absent"
591616 | Invalid_argument _ ->
592- invalid_arg " Source_map_io .Index.of_json: invalid sub-map object"
617+ invalid_arg " Source_map .Index.of_json: invalid sub-map object"
593618 in
594619 { offset; map }
595- | _ -> invalid_arg " Source_map_io .Index.of_json: section of unexpected type"
620+ | _ -> invalid_arg " Source_map .Index.of_json: section of unexpected type"
596621
597622 let of_json = function
598- | `Assoc fields -> (
623+ | `Assoc ((" version" , `Intlit version) :: fields)
624+ when version_is_valid (int_of_string version) -> (
599625 let string name json = Option. map ~f: string_of_stringlit (stringlit name json) in
600626 let file = string " file" fields in
601627 match List. assoc " sections" fields with
602628 | `List sections ->
603629 let sections = List. map ~f: section_of_json sections in
604- { version = 3 ; file; sections }
605- | _ -> invalid_arg " Source_map_io .Index.of_json: `sections` is not an array"
630+ { version = int_of_string version ; file; sections }
631+ | _ -> invalid_arg " Source_map .Index.of_json: `sections` is not an array"
606632 | exception Not_found ->
607- invalid_arg " Source_map_io .Index.of_json: no `sections` field" )
608- | _ -> invalid_arg " Source_map_io. of_json: map is not an object "
633+ invalid_arg " Source_map .Index.of_json: no `sections` field" )
634+ | _ -> invalid_arg " Source_map.Index. of_json"
609635
610636 let to_string m = Yojson.Raw. to_string (json m)
611637
612638 let to_file m file = Yojson.Raw. to_file file (json m)
639+
640+ let invariant { version; file = _ ; sections } =
641+ if not (version_is_valid version)
642+ then invalid_arg " Source_map.Index.invariant: invalid version" ;
643+ let _ : int =
644+ List. fold_left
645+ sections
646+ ~init: (- 1 )
647+ ~f: (fun acc { offset = { gen_line; gen_column } ; map } ->
648+ if gen_line < 0 || gen_column < 0
649+ then invalid_arg " Source_map.Index.invariant: invalid offset" ;
650+ if acc > = gen_line
651+ then
652+ invalid_arg
653+ " Source_map.Index.invariant: overlapping or unordered map in sections" ;
654+ Standard. invariant map;
655+ gen_line + Mappings. number_of_lines map.mappings)
656+ in
657+ ()
613658end
614659
615660type t =
@@ -621,7 +666,7 @@ let of_json = function
621666 match List. assoc " sections" fields with
622667 | _ -> Index (Index. of_json json)
623668 | exception Not_found -> Standard (Standard. of_json json))
624- | _ -> invalid_arg " Source_map_io .of_json: map is not an object"
669+ | _ -> invalid_arg " Source_map .of_json: map is not an object"
625670
626671let of_string s = of_json (Yojson.Raw. from_string s)
627672
@@ -636,6 +681,10 @@ let to_file x f =
636681 | Standard m -> Standard. to_file m f
637682 | Index i -> Index. to_file i f
638683
684+ let invariant = function
685+ | Standard m -> Standard. invariant m
686+ | Index i -> Index. invariant i
687+
639688type info =
640689 { mappings : Mappings .decoded
641690 ; sources : string list
0 commit comments