File: jsoo_minify.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 (127 lines) | stat: -rw-r--r-- 4,368 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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
(* Js_of_ocaml compiler
 * http://www.ocsigen.org/js_of_ocaml/
 * Copyright (C) 2013 Hugo Heuzard
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, with linking exception;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *)

open! Js_of_ocaml_compiler.Stdlib
open Js_of_ocaml_compiler

let error k = Format.ksprintf (fun s -> failwith s) k

let () = Sys.catch_break true

let f { Cmd_arg.common; output_file; use_stdin; files } =
  Jsoo_cmdline.Arg.eval common;
  let chop_extension s = try Filename.chop_extension s with Invalid_argument _ -> s in
  let with_output f =
    match output_file with
    | Some "-" -> f stdout
    | None when use_stdin -> f stdout
    | None | Some _ ->
        let file =
          match output_file with
          | Some f -> f
          | None ->
              if List.length files = 1
              then chop_extension (List.hd files) ^ ".min.js"
              else "a.min.js"
        in
        Filename.gen_file file f
  in
  let gen pp =
    let pretty = Config.Flag.pretty () in
    Pretty_print.set_compact pp (not pretty);
    Code.Var.set_pretty pretty;
    let error_of_pi pi =
      match pi with
      | { Parse_info.name = Some src; line; col; _ }
      | { Parse_info.src = Some src; line; col; _ } ->
          error "error at file:%S l:%d col:%d" src line col
      | { Parse_info.src = None; name = None; line; col; _ } ->
          error "error at l:%d col:%d" line col
    in
    let p =
      List.flatten
        (List.map files ~f:(fun file ->
             let lex = Parse_js.Lexer.of_file file in
             try Parse_js.parse lex with Parse_js.Parsing_error pi -> error_of_pi pi))
    in
    let p =
      if use_stdin
      then
        let lex = Parse_js.Lexer.of_channel stdin in
        try p @ Parse_js.parse lex with Parse_js.Parsing_error pi -> error_of_pi pi
      else p
    in
    let free = new Js_traverse.free in
    let (_ : Javascript.program) = free#program p in
    let toplevel_def_and_use =
      let state = free#state in
      Javascript.IdentSet.union state.def_var state.use
    in
    Javascript.IdentSet.iter
      (function
        | V _ -> ()
        | S { name = Utf8_string.Utf8 x; _ } -> Var_printer.add_reserved x)
      toplevel_def_and_use;
    let true_ () = true in
    let open Config in
    let passes : ((unit -> bool) * (unit -> Js_traverse.mapper)) list =
      [ ( Flag.shortvar
        , fun () -> (new Js_traverse.rename_variable ~esm:false :> Js_traverse.mapper) )
      ; (true_, fun () -> new Js_traverse.simpl)
      ; (true_, fun () -> new Js_traverse.clean)
      ]
    in
    let p =
      List.fold_left passes ~init:p ~f:(fun p (t, m) ->
          if t () then (m ())#program p else p)
    in
    let p = Js_assign.program p in
    let (_ : Source_map.info) = Js_output.program pp p in
    ()
  in
  with_output (fun out_channel ->
      let pp = Pretty_print.to_out_channel out_channel in
      gen pp)

let main =
  let t = Cmdliner.Term.(const f $ Cmd_arg.options) in
  Cmdliner.Cmd.v Cmd_arg.info t

let (_ : int) =
  try
    Cmdliner.Cmd.eval
      ~catch:false
      ~argv:(Jsoo_cmdline.normalize_argv ~warn:(warn "%s") Sys.argv)
      main
  with
  | (Match_failure _ | Assert_failure _ | Not_found) as exc ->
      let backtrace = Printexc.get_backtrace () in
      Format.eprintf
        "%s: You found a bug. Please report it at \
         https://github.com/ocsigen/js_of_ocaml/issues :@."
        Sys.argv.(0);
      Format.eprintf "Error: %s@." (Printexc.to_string exc);
      prerr_string backtrace;
      exit 1
  | Failure s ->
      Format.eprintf "%s: Error: %s@." Sys.argv.(0) s;
      exit 1
  | exc ->
      Format.eprintf "%s: Error: %s@." Sys.argv.(0) (Printexc.to_string exc);
      exit 1