UNPKG

10.1 kBJavaScriptView Raw
1"use strict";
2
3var to_ascii, to_base64;
4if (typeof Buffer == "undefined") {
5 to_ascii = atob;
6 to_base64 = btoa;
7} else if (typeof Buffer.alloc == "undefined") {
8 to_ascii = function(b64) {
9 return new Buffer(b64, "base64").toString();
10 };
11 to_base64 = function(str) {
12 return new Buffer(str).toString("base64");
13 };
14} else {
15 to_ascii = function(b64) {
16 return Buffer.from(b64, "base64").toString();
17 };
18 to_base64 = function(str) {
19 return Buffer.from(str).toString("base64");
20 };
21}
22
23function read_source_map(name, toplevel) {
24 var comments = toplevel.end.comments_after;
25 for (var i = comments.length; --i >= 0;) {
26 var comment = comments[i];
27 if (comment.type != "comment1") break;
28 var match = /^# ([^\s=]+)=(\S+)\s*$/.exec(comment.value);
29 if (!match) break;
30 if (match[1] == "sourceMappingURL") {
31 match = /^data:application\/json(;.*?)?;base64,(\S+)$/.exec(match[2]);
32 if (!match) break;
33 return to_ascii(match[2]);
34 }
35 }
36 AST_Node.warn("inline source map not found: " + name);
37}
38
39function parse_source_map(content) {
40 try {
41 return JSON.parse(content);
42 } catch (ex) {
43 throw new Error("invalid input source map: " + content);
44 }
45}
46
47function set_shorthand(name, options, keys) {
48 if (options[name]) {
49 keys.forEach(function(key) {
50 if (options[key]) {
51 if (typeof options[key] != "object") options[key] = {};
52 if (!(name in options[key])) options[key][name] = options[name];
53 }
54 });
55 }
56}
57
58function init_cache(cache) {
59 if (!cache) return;
60 if (!("props" in cache)) {
61 cache.props = new Dictionary();
62 } else if (!(cache.props instanceof Dictionary)) {
63 cache.props = Dictionary.fromObject(cache.props);
64 }
65}
66
67function to_json(cache) {
68 return {
69 props: cache.props.toObject()
70 };
71}
72
73function minify(files, options) {
74 try {
75 options = defaults(options, {
76 compress: {},
77 enclose: false,
78 ie8: false,
79 keep_fnames: false,
80 mangle: {},
81 nameCache: null,
82 output: {},
83 parse: {},
84 rename: undefined,
85 sourceMap: false,
86 timings: false,
87 toplevel: false,
88 warnings: false,
89 wrap: false,
90 }, true);
91 var timings = options.timings && {
92 start: Date.now()
93 };
94 if (options.rename === undefined) {
95 options.rename = options.compress && options.mangle;
96 }
97 set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
98 set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
99 set_shorthand("toplevel", options, [ "compress", "mangle" ]);
100 var quoted_props;
101 if (options.mangle) {
102 options.mangle = defaults(options.mangle, {
103 cache: options.nameCache && (options.nameCache.vars || {}),
104 eval: false,
105 ie8: false,
106 keep_fnames: false,
107 properties: false,
108 reserved: [],
109 toplevel: false,
110 }, true);
111 if (options.mangle.properties) {
112 if (typeof options.mangle.properties != "object") {
113 options.mangle.properties = {};
114 }
115 if (options.mangle.properties.keep_quoted) {
116 quoted_props = options.mangle.properties.reserved;
117 if (!Array.isArray(quoted_props)) quoted_props = [];
118 options.mangle.properties.reserved = quoted_props;
119 }
120 if (options.nameCache && !("cache" in options.mangle.properties)) {
121 options.mangle.properties.cache = options.nameCache.props || {};
122 }
123 }
124 init_cache(options.mangle.cache);
125 init_cache(options.mangle.properties.cache);
126 }
127 if (options.sourceMap) {
128 options.sourceMap = defaults(options.sourceMap, {
129 content: null,
130 filename: null,
131 includeSources: false,
132 root: null,
133 url: null,
134 }, true);
135 }
136 var warnings = [];
137 if (options.warnings) AST_Node.log_function(function(warning) {
138 warnings.push(warning);
139 }, options.warnings == "verbose");
140 if (timings) timings.parse = Date.now();
141 var source_maps, toplevel;
142 if (files instanceof AST_Toplevel) {
143 toplevel = files;
144 } else {
145 if (typeof files == "string") {
146 files = [ files ];
147 }
148 options.parse = options.parse || {};
149 options.parse.toplevel = null;
150 var source_map_content = options.sourceMap && options.sourceMap.content;
151 if (typeof source_map_content == "string" && source_map_content != "inline") {
152 source_map_content = parse_source_map(source_map_content);
153 }
154 source_maps = source_map_content && Object.create(null);
155 for (var name in files) if (HOP(files, name)) {
156 options.parse.filename = name;
157 options.parse.toplevel = toplevel = parse(files[name], options.parse);
158 if (source_maps) {
159 if (source_map_content == "inline") {
160 var inlined_content = read_source_map(name, toplevel);
161 if (inlined_content) {
162 source_maps[name] = parse_source_map(inlined_content);
163 }
164 } else {
165 source_maps[name] = source_map_content;
166 }
167 }
168 }
169 }
170 if (quoted_props) {
171 reserve_quoted_keys(toplevel, quoted_props);
172 }
173 [ "enclose", "wrap" ].forEach(function(action) {
174 var option = options[action];
175 if (!option) return;
176 var orig = toplevel.print_to_string().slice(0, -1);
177 toplevel = toplevel[action](option);
178 files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
179 });
180 if (timings) timings.rename = Date.now();
181 if (options.rename) {
182 toplevel.figure_out_scope(options.mangle);
183 toplevel.expand_names(options.mangle);
184 }
185 if (timings) timings.compress = Date.now();
186 if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
187 if (timings) timings.scope = Date.now();
188 if (options.mangle) toplevel.figure_out_scope(options.mangle);
189 if (timings) timings.mangle = Date.now();
190 if (options.mangle) {
191 toplevel.compute_char_frequency(options.mangle);
192 toplevel.mangle_names(options.mangle);
193 }
194 if (timings) timings.properties = Date.now();
195 if (options.mangle && options.mangle.properties) {
196 toplevel = mangle_properties(toplevel, options.mangle.properties);
197 }
198 if (timings) timings.output = Date.now();
199 var result = {};
200 if (options.output.ast) {
201 result.ast = toplevel;
202 }
203 if (!HOP(options.output, "code") || options.output.code) {
204 if (options.sourceMap) {
205 options.output.source_map = SourceMap({
206 content: options.sourceMap.includeSources,
207 file: options.sourceMap.filename,
208 orig: source_maps,
209 root: options.sourceMap.root
210 });
211 if (options.sourceMap.includeSources) {
212 if (files instanceof AST_Toplevel) {
213 throw new Error("original source content unavailable");
214 } else for (var name in files) if (HOP(files, name)) {
215 options.output.source_map.setSourceContent(name, files[name]);
216 }
217 }
218 }
219 delete options.output.ast;
220 delete options.output.code;
221 var stream = OutputStream(options.output);
222 toplevel.print(stream);
223 result.code = stream.get();
224 if (options.sourceMap) {
225 result.map = options.output.source_map.toString();
226 var url = options.sourceMap.url;
227 if (url) {
228 result.code = result.code.replace(/\n\/\/# sourceMappingURL=\S+\s*$/, "");
229 if (url == "inline") {
230 result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
231 } else {
232 result.code += "\n//# sourceMappingURL=" + url;
233 }
234 }
235 }
236 }
237 if (options.nameCache && options.mangle) {
238 if (options.mangle.cache) options.nameCache.vars = to_json(options.mangle.cache);
239 if (options.mangle.properties && options.mangle.properties.cache) {
240 options.nameCache.props = to_json(options.mangle.properties.cache);
241 }
242 }
243 if (timings) {
244 timings.end = Date.now();
245 result.timings = {
246 parse: 1e-3 * (timings.rename - timings.parse),
247 rename: 1e-3 * (timings.compress - timings.rename),
248 compress: 1e-3 * (timings.scope - timings.compress),
249 scope: 1e-3 * (timings.mangle - timings.scope),
250 mangle: 1e-3 * (timings.properties - timings.mangle),
251 properties: 1e-3 * (timings.output - timings.properties),
252 output: 1e-3 * (timings.end - timings.output),
253 total: 1e-3 * (timings.end - timings.start)
254 };
255 }
256 if (warnings.length) {
257 result.warnings = warnings;
258 }
259 return result;
260 } catch (ex) {
261 return { error: ex };
262 }
263}