source: imaps-frontend/node_modules/terser/lib/minify.js

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 14.2 KB
Line 
1"use strict";
2/* eslint-env browser, es6, node */
3
4import {
5 defaults,
6 map_from_object,
7 map_to_object,
8 HOP,
9} from "./utils/index.js";
10import { AST_Toplevel, AST_Node, walk, AST_Scope } from "./ast.js";
11import { parse } from "./parse.js";
12import { OutputStream } from "./output.js";
13import { Compressor } from "./compress/index.js";
14import { base54 } from "./scope.js";
15import { SourceMap } from "./sourcemap.js";
16import {
17 mangle_properties,
18 mangle_private_properties,
19 reserve_quoted_keys,
20 find_annotated_props,
21} from "./propmangle.js";
22
23// to/from base64 functions
24// Prefer built-in Buffer, if available, then use hack
25// https://developer.mozilla.org/en-US/docs/Glossary/Base64#The_Unicode_Problem
26var to_ascii = typeof Buffer !== "undefined"
27 ? (b64) => Buffer.from(b64, "base64").toString()
28 : (b64) => decodeURIComponent(escape(atob(b64)));
29var to_base64 = typeof Buffer !== "undefined"
30 ? (str) => Buffer.from(str).toString("base64")
31 : (str) => btoa(unescape(encodeURIComponent(str)));
32
33function read_source_map(code) {
34 var match = /(?:^|[^.])\/\/# sourceMappingURL=data:application\/json(;[\w=-]*)?;base64,([+/0-9A-Za-z]*=*)\s*$/.exec(code);
35 if (!match) {
36 console.warn("inline source map not found");
37 return null;
38 }
39 return to_ascii(match[2]);
40}
41
42function set_shorthand(name, options, keys) {
43 if (options[name]) {
44 keys.forEach(function(key) {
45 if (options[key]) {
46 if (typeof options[key] != "object") options[key] = {};
47 if (!(name in options[key])) options[key][name] = options[name];
48 }
49 });
50 }
51}
52
53function init_cache(cache) {
54 if (!cache) return;
55 if (!("props" in cache)) {
56 cache.props = new Map();
57 } else if (!(cache.props instanceof Map)) {
58 cache.props = map_from_object(cache.props);
59 }
60}
61
62function cache_to_json(cache) {
63 return {
64 props: map_to_object(cache.props)
65 };
66}
67
68function log_input(files, options, fs, debug_folder) {
69 if (!(fs && fs.writeFileSync && fs.mkdirSync)) {
70 return;
71 }
72
73 try {
74 fs.mkdirSync(debug_folder);
75 } catch (e) {
76 if (e.code !== "EEXIST") throw e;
77 }
78
79 const log_path = `${debug_folder}/terser-debug-${(Math.random() * 9999999) | 0}.log`;
80
81 options = options || {};
82
83 const options_str = JSON.stringify(options, (_key, thing) => {
84 if (typeof thing === "function") return "[Function " + thing.toString() + "]";
85 if (thing instanceof RegExp) return "[RegExp " + thing.toString() + "]";
86 return thing;
87 }, 4);
88
89 const files_str = (file) => {
90 if (typeof file === "object" && options.parse && options.parse.spidermonkey) {
91 return JSON.stringify(file, null, 2);
92 } else if (typeof file === "object") {
93 return Object.keys(file)
94 .map((key) => key + ": " + files_str(file[key]))
95 .join("\n\n");
96 } else if (typeof file === "string") {
97 return "```\n" + file + "\n```";
98 } else {
99 return file; // What do?
100 }
101 };
102
103 fs.writeFileSync(log_path, "Options: \n" + options_str + "\n\nInput files:\n\n" + files_str(files) + "\n");
104}
105
106function* minify_sync_or_async(files, options, _fs_module) {
107 if (
108 _fs_module
109 && typeof process === "object"
110 && process.env
111 && typeof process.env.TERSER_DEBUG_DIR === "string"
112 ) {
113 log_input(files, options, _fs_module, process.env.TERSER_DEBUG_DIR);
114 }
115
116 options = defaults(options, {
117 compress: {},
118 ecma: undefined,
119 enclose: false,
120 ie8: false,
121 keep_classnames: undefined,
122 keep_fnames: false,
123 mangle: {},
124 module: false,
125 nameCache: null,
126 output: null,
127 format: null,
128 parse: {},
129 rename: undefined,
130 safari10: false,
131 sourceMap: false,
132 spidermonkey: false,
133 timings: false,
134 toplevel: false,
135 warnings: false,
136 wrap: false,
137 }, true);
138
139 var timings = options.timings && {
140 start: Date.now()
141 };
142 if (options.keep_classnames === undefined) {
143 options.keep_classnames = options.keep_fnames;
144 }
145 if (options.rename === undefined) {
146 options.rename = options.compress && options.mangle;
147 }
148 if (options.output && options.format) {
149 throw new Error("Please only specify either output or format option, preferrably format.");
150 }
151 options.format = options.format || options.output || {};
152 set_shorthand("ecma", options, [ "parse", "compress", "format" ]);
153 set_shorthand("ie8", options, [ "compress", "mangle", "format" ]);
154 set_shorthand("keep_classnames", options, [ "compress", "mangle" ]);
155 set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
156 set_shorthand("module", options, [ "parse", "compress", "mangle" ]);
157 set_shorthand("safari10", options, [ "mangle", "format" ]);
158 set_shorthand("toplevel", options, [ "compress", "mangle" ]);
159 set_shorthand("warnings", options, [ "compress" ]); // legacy
160 var quoted_props;
161 if (options.mangle) {
162 options.mangle = defaults(options.mangle, {
163 cache: options.nameCache && (options.nameCache.vars || {}),
164 eval: false,
165 ie8: false,
166 keep_classnames: false,
167 keep_fnames: false,
168 module: false,
169 nth_identifier: base54,
170 properties: false,
171 reserved: [],
172 safari10: false,
173 toplevel: false,
174 }, true);
175 if (options.mangle.properties) {
176 if (typeof options.mangle.properties != "object") {
177 options.mangle.properties = {};
178 }
179 if (options.mangle.properties.keep_quoted) {
180 quoted_props = options.mangle.properties.reserved;
181 if (!Array.isArray(quoted_props)) quoted_props = [];
182 options.mangle.properties.reserved = quoted_props;
183 }
184 if (options.nameCache && !("cache" in options.mangle.properties)) {
185 options.mangle.properties.cache = options.nameCache.props || {};
186 }
187 }
188 init_cache(options.mangle.cache);
189 init_cache(options.mangle.properties.cache);
190 }
191 if (options.sourceMap) {
192 options.sourceMap = defaults(options.sourceMap, {
193 asObject: false,
194 content: null,
195 filename: null,
196 includeSources: false,
197 root: null,
198 url: null,
199 }, true);
200 }
201
202 // -- Parse phase --
203 if (timings) timings.parse = Date.now();
204 var toplevel;
205 if (files instanceof AST_Toplevel) {
206 toplevel = files;
207 } else {
208 if (typeof files == "string" || (options.parse.spidermonkey && !Array.isArray(files))) {
209 files = [ files ];
210 }
211 options.parse = options.parse || {};
212 options.parse.toplevel = null;
213
214 if (options.parse.spidermonkey) {
215 options.parse.toplevel = AST_Node.from_mozilla_ast(Object.keys(files).reduce(function(toplevel, name) {
216 if (!toplevel) return files[name];
217 toplevel.body = toplevel.body.concat(files[name].body);
218 return toplevel;
219 }, null));
220 } else {
221 delete options.parse.spidermonkey;
222
223 for (var name in files) if (HOP(files, name)) {
224 options.parse.filename = name;
225 options.parse.toplevel = parse(files[name], options.parse);
226 if (options.sourceMap && options.sourceMap.content == "inline") {
227 if (Object.keys(files).length > 1)
228 throw new Error("inline source map only works with singular input");
229 options.sourceMap.content = read_source_map(files[name]);
230 }
231 }
232 }
233 if (options.parse.toplevel === null) {
234 throw new Error("no source file given");
235 }
236
237 toplevel = options.parse.toplevel;
238 }
239 if (quoted_props && options.mangle.properties.keep_quoted !== "strict") {
240 reserve_quoted_keys(toplevel, quoted_props);
241 }
242 var annotated_props;
243 if (options.mangle && options.mangle.properties) {
244 annotated_props = find_annotated_props(toplevel);
245 }
246 if (options.wrap) {
247 toplevel = toplevel.wrap_commonjs(options.wrap);
248 }
249 if (options.enclose) {
250 toplevel = toplevel.wrap_enclose(options.enclose);
251 }
252 if (timings) timings.rename = Date.now();
253 // disable rename on harmony due to expand_names bug in for-of loops
254 // https://github.com/mishoo/UglifyJS2/issues/2794
255 if (0 && options.rename) {
256 toplevel.figure_out_scope(options.mangle);
257 toplevel.expand_names(options.mangle);
258 }
259
260 // -- Compress phase --
261 if (timings) timings.compress = Date.now();
262 if (options.compress) {
263 toplevel = new Compressor(options.compress, {
264 mangle_options: options.mangle
265 }).compress(toplevel);
266 }
267
268 // -- Mangle phase --
269 if (timings) timings.scope = Date.now();
270 if (options.mangle) toplevel.figure_out_scope(options.mangle);
271 if (timings) timings.mangle = Date.now();
272 if (options.mangle) {
273 toplevel.compute_char_frequency(options.mangle);
274 toplevel.mangle_names(options.mangle);
275 toplevel = mangle_private_properties(toplevel, options.mangle);
276 }
277 if (timings) timings.properties = Date.now();
278 if (options.mangle && options.mangle.properties) {
279 toplevel = mangle_properties(toplevel, options.mangle.properties, annotated_props);
280 }
281
282 // Format phase
283 if (timings) timings.format = Date.now();
284 var result = {};
285 if (options.format.ast) {
286 result.ast = toplevel;
287 }
288 if (options.format.spidermonkey) {
289 result.ast = toplevel.to_mozilla_ast();
290 }
291 let format_options;
292 if (!HOP(options.format, "code") || options.format.code) {
293 // Make a shallow copy so that we can modify without mutating the user's input.
294 format_options = {...options.format};
295 if (!format_options.ast) {
296 // Destroy stuff to save RAM. (unless the deprecated `ast` option is on)
297 format_options._destroy_ast = true;
298
299 walk(toplevel, node => {
300 if (node instanceof AST_Scope) {
301 node.variables = undefined;
302 node.enclosed = undefined;
303 node.parent_scope = undefined;
304 }
305 if (node.block_scope) {
306 node.block_scope.variables = undefined;
307 node.block_scope.enclosed = undefined;
308 node.block_scope.parent_scope = undefined;
309 }
310 });
311 }
312
313 if (options.sourceMap) {
314 if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
315 throw new Error("original source content unavailable");
316 }
317 format_options.source_map = yield* SourceMap({
318 file: options.sourceMap.filename,
319 orig: options.sourceMap.content,
320 root: options.sourceMap.root,
321 files: options.sourceMap.includeSources ? files : null,
322 });
323 }
324 delete format_options.ast;
325 delete format_options.code;
326 delete format_options.spidermonkey;
327 var stream = OutputStream(format_options);
328 toplevel.print(stream);
329 result.code = stream.get();
330 if (options.sourceMap) {
331 Object.defineProperty(result, "map", {
332 configurable: true,
333 enumerable: true,
334 get() {
335 const map = format_options.source_map.getEncoded();
336 return (result.map = options.sourceMap.asObject ? map : JSON.stringify(map));
337 },
338 set(value) {
339 Object.defineProperty(result, "map", {
340 value,
341 writable: true,
342 });
343 }
344 });
345 result.decoded_map = format_options.source_map.getDecoded();
346 if (options.sourceMap.url == "inline") {
347 var sourceMap = typeof result.map === "object" ? JSON.stringify(result.map) : result.map;
348 result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(sourceMap);
349 } else if (options.sourceMap.url) {
350 result.code += "\n//# sourceMappingURL=" + options.sourceMap.url;
351 }
352 }
353 }
354 if (options.nameCache && options.mangle) {
355 if (options.mangle.cache) options.nameCache.vars = cache_to_json(options.mangle.cache);
356 if (options.mangle.properties && options.mangle.properties.cache) {
357 options.nameCache.props = cache_to_json(options.mangle.properties.cache);
358 }
359 }
360 if (format_options && format_options.source_map) {
361 format_options.source_map.destroy();
362 }
363 if (timings) {
364 timings.end = Date.now();
365 result.timings = {
366 parse: 1e-3 * (timings.rename - timings.parse),
367 rename: 1e-3 * (timings.compress - timings.rename),
368 compress: 1e-3 * (timings.scope - timings.compress),
369 scope: 1e-3 * (timings.mangle - timings.scope),
370 mangle: 1e-3 * (timings.properties - timings.mangle),
371 properties: 1e-3 * (timings.format - timings.properties),
372 format: 1e-3 * (timings.end - timings.format),
373 total: 1e-3 * (timings.end - timings.start)
374 };
375 }
376 return result;
377}
378
379async function minify(files, options, _fs_module) {
380 const gen = minify_sync_or_async(files, options, _fs_module);
381
382 let yielded;
383 let val;
384 do {
385 val = gen.next(await yielded);
386 yielded = val.value;
387 } while (!val.done);
388
389 return val.value;
390}
391
392function minify_sync(files, options, _fs_module) {
393 const gen = minify_sync_or_async(files, options, _fs_module);
394
395 let yielded;
396 let val;
397 do {
398 if (yielded && typeof yielded.then === "function") {
399 throw new Error("minify_sync cannot be used with the legacy source-map module");
400 }
401 val = gen.next(yielded);
402 yielded = val.value;
403 } while (!val.done);
404
405 return val.value;
406}
407
408export {
409 minify,
410 minify_sync,
411 to_ascii,
412};
Note: See TracBrowser for help on using the repository browser.