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

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

F4 Finalna Verzija

  • Property mode set to 100644
File size: 14.6 KB
RevLine 
[79a0317]1/***********************************************************************
2
3 A JavaScript tokenizer / parser / beautifier / compressor.
4 https://github.com/mishoo/UglifyJS2
5
6 -------------------------------- (C) ---------------------------------
7
8 Author: Mihai Bazon
9 <mihai.bazon@gmail.com>
10 http://mihai.bazon.net/blog
11
12 Distributed under the BSD license:
13
14 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
15
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions
18 are met:
19
20 * Redistributions of source code must retain the above
21 copyright notice, this list of conditions and the following
22 disclaimer.
23
24 * Redistributions in binary form must reproduce the above
25 copyright notice, this list of conditions and the following
26 disclaimer in the documentation and/or other materials
27 provided with the distribution.
28
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
30 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
33 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
38 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
39 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 SUCH DAMAGE.
41
42 ***********************************************************************/
43
44"use strict";
45/* global global, self */
46
47import {
48 defaults,
49 push_uniq,
50 has_annotation,
51 clear_annotation,
52} from "./utils/index.js";
53import { base54 } from "./scope.js";
54import {
55 AST_Binary,
56 AST_Call,
57 AST_ClassPrivateProperty,
58 AST_Conditional,
59 AST_Dot,
60 AST_DotHash,
61 AST_ObjectKeyVal,
62 AST_ObjectProperty,
63 AST_PrivateMethod,
64 AST_PrivateGetter,
65 AST_PrivateSetter,
66 AST_PrivateIn,
67 AST_Sequence,
68 AST_String,
69 AST_Sub,
70 TreeTransformer,
71 TreeWalker,
72 _KEY,
73 _MANGLEPROP,
74
75 walk,
76} from "./ast.js";
77import { domprops } from "../tools/domprops.js";
78
79function find_builtins(reserved) {
80 domprops.forEach(add);
81
82 // Compatibility fix for some standard defined globals not defined on every js environment
83 var new_globals = ["Symbol", "Map", "Promise", "Proxy", "Reflect", "Set", "WeakMap", "WeakSet"];
84 var objects = {};
85 var global_ref = typeof global === "object" ? global : self;
86
87 new_globals.forEach(function (new_global) {
88 objects[new_global] = global_ref[new_global] || function() {};
89 });
90
91 [
92 "null",
93 "true",
94 "false",
95 "NaN",
96 "Infinity",
97 "-Infinity",
98 "undefined",
99 ].forEach(add);
100 [ Object, Array, Function, Number,
101 String, Boolean, Error, Math,
102 Date, RegExp, objects.Symbol, ArrayBuffer,
103 DataView, decodeURI, decodeURIComponent,
104 encodeURI, encodeURIComponent, eval, EvalError,
105 Float32Array, Float64Array, Int8Array, Int16Array,
106 Int32Array, isFinite, isNaN, JSON, objects.Map, parseFloat,
107 parseInt, objects.Promise, objects.Proxy, RangeError, ReferenceError,
108 objects.Reflect, objects.Set, SyntaxError, TypeError, Uint8Array,
109 Uint8ClampedArray, Uint16Array, Uint32Array, URIError,
110 objects.WeakMap, objects.WeakSet
111 ].forEach(function(ctor) {
112 Object.getOwnPropertyNames(ctor).map(add);
113 if (ctor.prototype) {
114 Object.getOwnPropertyNames(ctor.prototype).map(add);
115 }
116 });
117 function add(name) {
118 reserved.add(name);
119 }
120}
121
122function reserve_quoted_keys(ast, reserved) {
123 function add(name) {
124 push_uniq(reserved, name);
125 }
126
127 ast.walk(new TreeWalker(function(node) {
128 if (node instanceof AST_ObjectKeyVal && node.quote) {
129 add(node.key);
130 } else if (node instanceof AST_ObjectProperty && node.quote) {
131 add(node.key.name);
132 } else if (node instanceof AST_Sub) {
133 addStrings(node.property, add);
134 }
135 }));
136}
137
138function addStrings(node, add) {
139 node.walk(new TreeWalker(function(node) {
140 if (node instanceof AST_Sequence) {
141 addStrings(node.tail_node(), add);
142 } else if (node instanceof AST_String) {
143 add(node.value);
144 } else if (node instanceof AST_Conditional) {
145 addStrings(node.consequent, add);
146 addStrings(node.alternative, add);
147 }
148 return true;
149 }));
150}
151
152function mangle_private_properties(ast, options) {
153 var cprivate = -1;
154 var private_cache = new Map();
155 var nth_identifier = options.nth_identifier || base54;
156
157 ast = ast.transform(new TreeTransformer(function(node) {
158 if (
159 node instanceof AST_ClassPrivateProperty
160 || node instanceof AST_PrivateMethod
161 || node instanceof AST_PrivateGetter
162 || node instanceof AST_PrivateSetter
163 || node instanceof AST_PrivateIn
164 ) {
165 node.key.name = mangle_private(node.key.name);
166 } else if (node instanceof AST_DotHash) {
167 node.property = mangle_private(node.property);
168 }
169 }));
170 return ast;
171
172 function mangle_private(name) {
173 let mangled = private_cache.get(name);
174 if (!mangled) {
175 mangled = nth_identifier.get(++cprivate);
176 private_cache.set(name, mangled);
177 }
178
179 return mangled;
180 }
181}
182
183function find_annotated_props(ast) {
184 var annotated_props = new Set();
185 walk(ast, node => {
186 if (
187 node instanceof AST_ClassPrivateProperty
188 || node instanceof AST_PrivateMethod
189 || node instanceof AST_PrivateGetter
190 || node instanceof AST_PrivateSetter
191 || node instanceof AST_DotHash
192 ) {
193 // handled by mangle_private_properties
194 } else if (node instanceof AST_ObjectKeyVal) {
195 if (typeof node.key == "string" && has_annotation(node, _MANGLEPROP)) {
196 annotated_props.add(node.key);
197 }
198 } else if (node instanceof AST_ObjectProperty) {
199 // setter or getter, since KeyVal is handled above
200 if (has_annotation(node, _MANGLEPROP)) {
201 annotated_props.add(node.key.name);
202 }
203 } else if (node instanceof AST_Dot) {
204 if (has_annotation(node, _MANGLEPROP)) {
205 annotated_props.add(node.property);
206 }
207 } else if (node instanceof AST_Sub) {
208 if (node.property instanceof AST_String && has_annotation(node, _MANGLEPROP)) {
209 annotated_props.add(node.property.value);
210 }
211 }
212 });
213 return annotated_props;
214}
215
216function mangle_properties(ast, options, annotated_props = find_annotated_props(ast)) {
217 options = defaults(options, {
218 builtins: false,
219 cache: null,
220 debug: false,
221 keep_quoted: false,
222 nth_identifier: base54,
223 only_cache: false,
224 regex: null,
225 reserved: null,
226 undeclared: false,
227 only_annotated: false,
228 }, true);
229
230 var nth_identifier = options.nth_identifier;
231
232 var reserved_option = options.reserved;
233 if (!Array.isArray(reserved_option)) reserved_option = [reserved_option];
234 var reserved = new Set(reserved_option);
235 if (!options.builtins) find_builtins(reserved);
236
237 var cname = -1;
238
239 var cache;
240 if (options.cache) {
241 cache = options.cache.props;
242 } else {
243 cache = new Map();
244 }
245
246 var only_annotated = options.only_annotated;
247 var regex = options.regex && new RegExp(options.regex);
248
249 // note debug is either false (disabled), or a string of the debug suffix to use (enabled).
250 // note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
251 // the same as passing an empty string.
252 var debug = options.debug !== false;
253 var debug_name_suffix;
254 if (debug) {
255 debug_name_suffix = (options.debug === true ? "" : options.debug);
256 }
257
258 var names_to_mangle = new Set();
259 var unmangleable = new Set();
260 // Track each already-mangled name to prevent nth_identifier from generating
261 // the same name.
262 cache.forEach((mangled_name) => unmangleable.add(mangled_name));
263
264 var keep_quoted = !!options.keep_quoted;
265
266 // step 1: find candidates to mangle
267 ast.walk(new TreeWalker(function(node) {
268 if (
269 node instanceof AST_ClassPrivateProperty
270 || node instanceof AST_PrivateMethod
271 || node instanceof AST_PrivateGetter
272 || node instanceof AST_PrivateSetter
273 || node instanceof AST_DotHash
274 ) {
275 // handled by mangle_private_properties
276 } else if (node instanceof AST_ObjectKeyVal) {
277 if (typeof node.key == "string" && (!keep_quoted || !node.quote)) {
278 add(node.key);
279 }
280 } else if (node instanceof AST_ObjectProperty) {
281 // setter or getter, since KeyVal is handled above
282 if (!keep_quoted || !node.quote) {
283 add(node.key.name);
284 }
285 } else if (node instanceof AST_Dot) {
286 var declared = !!options.undeclared;
287 if (!declared) {
288 var root = node;
289 while (root.expression) {
290 root = root.expression;
291 }
292 declared = !(root.thedef && root.thedef.undeclared);
293 }
294 if (declared &&
295 (!keep_quoted || !node.quote)) {
296 add(node.property);
297 }
298 } else if (node instanceof AST_Sub) {
299 if (!keep_quoted) {
300 addStrings(node.property, add);
301 }
302 } else if (node instanceof AST_Call
303 && node.expression.print_to_string() == "Object.defineProperty") {
304 addStrings(node.args[1], add);
305 } else if (node instanceof AST_Binary && node.operator === "in") {
306 addStrings(node.left, add);
307 } else if (node instanceof AST_String && has_annotation(node, _KEY)) {
308 add(node.value);
309 }
310 }));
311
312 // step 2: transform the tree, renaming properties
313 return ast.transform(new TreeTransformer(function(node) {
314 if (
315 node instanceof AST_ClassPrivateProperty
316 || node instanceof AST_PrivateMethod
317 || node instanceof AST_PrivateGetter
318 || node instanceof AST_PrivateSetter
319 || node instanceof AST_DotHash
320 ) {
321 // handled by mangle_private_properties
322 } else if (node instanceof AST_ObjectKeyVal) {
323 if (typeof node.key == "string" && (!keep_quoted || !node.quote)) {
324 node.key = mangle(node.key);
325 }
326 } else if (node instanceof AST_ObjectProperty) {
327 // setter, getter, method or class field
328 if (!keep_quoted || !node.quote) {
329 if (!node.computed_key()) {
330 node.key.name = mangle(node.key.name);
331 }
332 }
333 } else if (node instanceof AST_Dot) {
334 if (!keep_quoted || !node.quote) {
335 node.property = mangle(node.property);
336 }
337 } else if (!keep_quoted && node instanceof AST_Sub) {
338 node.property = mangleStrings(node.property);
339 } else if (node instanceof AST_Call
340 && node.expression.print_to_string() == "Object.defineProperty") {
341 node.args[1] = mangleStrings(node.args[1]);
342 } else if (node instanceof AST_Binary && node.operator === "in") {
343 node.left = mangleStrings(node.left);
344 } else if (node instanceof AST_String && has_annotation(node, _KEY)) {
345 // Clear _KEY annotation to prevent double mangling
346 clear_annotation(node, _KEY);
347 node.value = mangle(node.value);
348 }
349 }));
350
351 // only function declarations after this line
352
353 function can_mangle(name) {
354 if (unmangleable.has(name)) return false;
355 if (reserved.has(name)) return false;
356 if (options.only_cache) {
357 return cache.has(name);
358 }
359 if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
360 return true;
361 }
362
363 function should_mangle(name) {
364 if (only_annotated && !annotated_props.has(name)) return false;
365 if (regex && !regex.test(name)) {
366 return annotated_props.has(name);
367 }
368 if (reserved.has(name)) return false;
369 return cache.has(name)
370 || names_to_mangle.has(name);
371 }
372
373 function add(name) {
374 if (can_mangle(name)) {
375 names_to_mangle.add(name);
376 }
377
378 if (!should_mangle(name)) {
379 unmangleable.add(name);
380 }
381 }
382
383 function mangle(name) {
384 if (!should_mangle(name)) {
385 return name;
386 }
387
388 var mangled = cache.get(name);
389 if (!mangled) {
390 if (debug) {
391 // debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
392 var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
393
394 if (can_mangle(debug_mangled)) {
395 mangled = debug_mangled;
396 }
397 }
398
399 // either debug mode is off, or it is on and we could not use the mangled name
400 if (!mangled) {
401 do {
402 mangled = nth_identifier.get(++cname);
403 } while (!can_mangle(mangled));
404 }
405
406 cache.set(name, mangled);
407 }
408 return mangled;
409 }
410
411 function mangleStrings(node) {
412 return node.transform(new TreeTransformer(function(node) {
413 if (node instanceof AST_Sequence) {
414 var last = node.expressions.length - 1;
415 node.expressions[last] = mangleStrings(node.expressions[last]);
416 } else if (node instanceof AST_String) {
417 // Clear _KEY annotation to prevent double mangling
418 clear_annotation(node, _KEY);
419 node.value = mangle(node.value);
420 } else if (node instanceof AST_Conditional) {
421 node.consequent = mangleStrings(node.consequent);
422 node.alternative = mangleStrings(node.alternative);
423 }
424 return node;
425 }));
426 }
427}
428
429export {
430 reserve_quoted_keys,
431 mangle_properties,
432 mangle_private_properties,
433 find_annotated_props,
434};
Note: See TracBrowser for help on using the repository browser.