Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / handlebars / node_modules / uglify-js / lib / scope.js
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
46 function SymbolDef(scope, index, orig) {
47     this.name = orig.name;
48     this.orig = [ orig ];
49     this.scope = scope;
50     this.references = [];
51     this.global = false;
52     this.mangled_name = null;
53     this.undeclared = false;
54     this.index = index;
55     this.id = SymbolDef.next_id++;
56 };
57
58 SymbolDef.next_id = 1;
59
60 SymbolDef.prototype = {
61     unmangleable: function(options) {
62         if (!options) options = {};
63
64         return (this.global && !options.toplevel)
65             || this.undeclared
66             || (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
67             || (options.keep_fnames
68                 && (this.orig[0] instanceof AST_SymbolLambda
69                     || this.orig[0] instanceof AST_SymbolDefun));
70     },
71     mangle: function(options) {
72         var cache = options.cache && options.cache.props;
73         if (this.global && cache && cache.has(this.name)) {
74             this.mangled_name = cache.get(this.name);
75         }
76         else if (!this.mangled_name && !this.unmangleable(options)) {
77             var s = this.scope;
78             if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
79                 s = s.parent_scope;
80             this.mangled_name = s.next_mangled(options, this);
81             if (this.global && cache) {
82                 cache.set(this.name, this.mangled_name);
83             }
84         }
85     }
86 };
87
88 AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
89     options = defaults(options, {
90         screw_ie8: true,
91         cache: null
92     });
93
94     // pass 1: setup scope chaining and handle definitions
95     var self = this;
96     var scope = self.parent_scope = null;
97     var labels = new Dictionary();
98     var defun = null;
99     var tw = new TreeWalker(function(node, descend){
100         if (node instanceof AST_Catch) {
101             var save_scope = scope;
102             scope = new AST_Scope(node);
103             scope.init_scope_vars();
104             scope.parent_scope = save_scope;
105             descend();
106             scope = save_scope;
107             return true;
108         }
109         if (node instanceof AST_Scope) {
110             node.init_scope_vars();
111             var save_scope = node.parent_scope = scope;
112             var save_defun = defun;
113             var save_labels = labels;
114             defun = scope = node;
115             labels = new Dictionary();
116             descend();
117             scope = save_scope;
118             defun = save_defun;
119             labels = save_labels;
120             return true;        // don't descend again in TreeWalker
121         }
122         if (node instanceof AST_LabeledStatement) {
123             var l = node.label;
124             if (labels.has(l.name)) {
125                 throw new Error(string_template("Label {name} defined twice", l));
126             }
127             labels.set(l.name, l);
128             descend();
129             labels.del(l.name);
130             return true;        // no descend again
131         }
132         if (node instanceof AST_With) {
133             for (var s = scope; s; s = s.parent_scope)
134                 s.uses_with = true;
135             return;
136         }
137         if (node instanceof AST_Symbol) {
138             node.scope = scope;
139         }
140         if (node instanceof AST_Label) {
141             node.thedef = node;
142             node.references = [];
143         }
144         if (node instanceof AST_SymbolLambda) {
145             defun.def_function(node);
146         }
147         else if (node instanceof AST_SymbolDefun) {
148             // Careful here, the scope where this should be defined is
149             // the parent scope.  The reason is that we enter a new
150             // scope when we encounter the AST_Defun node (which is
151             // instanceof AST_Scope) but we get to the symbol a bit
152             // later.
153             (node.scope = defun.parent_scope).def_function(node);
154         }
155         else if (node instanceof AST_SymbolVar
156                  || node instanceof AST_SymbolConst) {
157             defun.def_variable(node);
158         }
159         else if (node instanceof AST_SymbolCatch) {
160             scope.def_variable(node);
161         }
162         else if (node instanceof AST_LabelRef) {
163             var sym = labels.get(node.name);
164             if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
165                 name: node.name,
166                 line: node.start.line,
167                 col: node.start.col
168             }));
169             node.thedef = sym;
170         }
171     });
172     self.walk(tw);
173
174     // pass 2: find back references and eval
175     var func = null;
176     var globals = self.globals = new Dictionary();
177     var tw = new TreeWalker(function(node, descend){
178         if (node instanceof AST_Lambda) {
179             var prev_func = func;
180             func = node;
181             descend();
182             func = prev_func;
183             return true;
184         }
185         if (node instanceof AST_LoopControl && node.label) {
186             node.label.thedef.references.push(node);
187             return true;
188         }
189         if (node instanceof AST_SymbolRef) {
190             var name = node.name;
191             if (name == "eval" && tw.parent() instanceof AST_Call) {
192                 for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
193                     s.uses_eval = true;
194                 }
195             }
196             var sym = node.scope.find_variable(name);
197             if (node.scope instanceof AST_Lambda && name == "arguments") {
198                 node.scope.uses_arguments = true;
199             }
200             if (!sym) {
201                 sym = self.def_global(node);
202             }
203             node.thedef = sym;
204             node.reference(options);
205             return true;
206         }
207     });
208     self.walk(tw);
209
210     // pass 3: fix up any scoping issue with IE8
211     if (!options.screw_ie8) {
212         self.walk(new TreeWalker(function(node, descend) {
213             if (node instanceof AST_SymbolCatch) {
214                 var name = node.name;
215                 var scope = node.thedef.scope.parent_scope;
216                 var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
217                 node.thedef.references.forEach(function(ref) {
218                     ref.thedef = def;
219                     ref.reference(options);
220                 });
221                 node.thedef = def;
222                 return true;
223             }
224         }));
225     }
226
227     if (options.cache) {
228         this.cname = options.cache.cname;
229     }
230 });
231
232 AST_Toplevel.DEFMETHOD("def_global", function(node){
233     var globals = this.globals, name = node.name;
234     if (globals.has(name)) {
235         return globals.get(name);
236     } else {
237         var g = new SymbolDef(this, globals.size(), node);
238         g.undeclared = true;
239         g.global = true;
240         globals.set(name, g);
241         return g;
242     }
243 });
244
245 AST_Scope.DEFMETHOD("init_scope_vars", function(){
246     this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
247     this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
248     this.uses_with = false;   // will be set to true if this or some nested scope uses the `with` statement
249     this.uses_eval = false;   // will be set to true if this or nested scope uses the global `eval`
250     this.parent_scope = null; // the parent scope
251     this.enclosed = [];       // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
252     this.cname = -1;          // the current index for mangling functions/variables
253 });
254
255 AST_Lambda.DEFMETHOD("init_scope_vars", function(){
256     AST_Scope.prototype.init_scope_vars.apply(this, arguments);
257     this.uses_arguments = false;
258
259     var symbol = new AST_VarDef({ name: "arguments", start: this.start, end: this.end });
260     var def = new SymbolDef(this, this.variables.size(), symbol);
261     this.variables.set(symbol.name, def);
262 });
263
264 AST_SymbolRef.DEFMETHOD("reference", function(options) {
265     var def = this.definition();
266     def.references.push(this);
267     var s = this.scope;
268     while (s) {
269         push_uniq(s.enclosed, def);
270         if (options.keep_fnames) {
271             s.functions.each(function(d) {
272                 push_uniq(def.scope.enclosed, d);
273             });
274         }
275         if (s === def.scope) break;
276         s = s.parent_scope;
277     }
278 });
279
280 AST_Scope.DEFMETHOD("find_variable", function(name){
281     if (name instanceof AST_Symbol) name = name.name;
282     return this.variables.get(name)
283         || (this.parent_scope && this.parent_scope.find_variable(name));
284 });
285
286 AST_Scope.DEFMETHOD("def_function", function(symbol){
287     this.functions.set(symbol.name, this.def_variable(symbol));
288 });
289
290 AST_Scope.DEFMETHOD("def_variable", function(symbol){
291     var def;
292     if (!this.variables.has(symbol.name)) {
293         def = new SymbolDef(this, this.variables.size(), symbol);
294         this.variables.set(symbol.name, def);
295         def.global = !this.parent_scope;
296     } else {
297         def = this.variables.get(symbol.name);
298         def.orig.push(symbol);
299     }
300     return symbol.thedef = def;
301 });
302
303 AST_Scope.DEFMETHOD("next_mangled", function(options){
304     var ext = this.enclosed;
305     out: while (true) {
306         var m = base54(++this.cname);
307         if (!is_identifier(m)) continue; // skip over "do"
308
309         // https://github.com/mishoo/UglifyJS2/issues/242 -- do not
310         // shadow a name excepted from mangling.
311         if (options.except.indexOf(m) >= 0) continue;
312
313         // we must ensure that the mangled name does not shadow a name
314         // from some parent scope that is referenced in this or in
315         // inner scopes.
316         for (var i = ext.length; --i >= 0;) {
317             var sym = ext[i];
318             var name = sym.mangled_name || (sym.unmangleable(options) && sym.name);
319             if (m == name) continue out;
320         }
321         return m;
322     }
323 });
324
325 AST_Function.DEFMETHOD("next_mangled", function(options, def){
326     // #179, #326
327     // in Safari strict mode, something like (function x(x){...}) is a syntax error;
328     // a function expression's argument cannot shadow the function expression's name
329
330     var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
331
332     // the function's mangled_name is null when keep_fnames is true
333     var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null;
334
335     while (true) {
336         var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
337         if (!tricky_name || tricky_name != name)
338             return name;
339     }
340 });
341
342 AST_Symbol.DEFMETHOD("unmangleable", function(options){
343     return this.definition().unmangleable(options);
344 });
345
346 // property accessors are not mangleable
347 AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){
348     return true;
349 });
350
351 // labels are always mangleable
352 AST_Label.DEFMETHOD("unmangleable", function(){
353     return false;
354 });
355
356 AST_Symbol.DEFMETHOD("unreferenced", function(){
357     return this.definition().references.length == 0
358         && !(this.scope.uses_eval || this.scope.uses_with);
359 });
360
361 AST_Symbol.DEFMETHOD("undeclared", function(){
362     return this.definition().undeclared;
363 });
364
365 AST_LabelRef.DEFMETHOD("undeclared", function(){
366     return false;
367 });
368
369 AST_Label.DEFMETHOD("undeclared", function(){
370     return false;
371 });
372
373 AST_Symbol.DEFMETHOD("definition", function(){
374     return this.thedef;
375 });
376
377 AST_Symbol.DEFMETHOD("global", function(){
378     return this.definition().global;
379 });
380
381 AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
382     return defaults(options, {
383         except      : [],
384         eval        : false,
385         sort        : false, // Ignored. Flag retained for backwards compatibility.
386         toplevel    : false,
387         screw_ie8   : true,
388         keep_fnames : false
389     });
390 });
391
392 AST_Toplevel.DEFMETHOD("mangle_names", function(options){
393     options = this._default_mangler_options(options);
394
395     // Never mangle arguments
396     options.except.push('arguments');
397
398     // We only need to mangle declaration nodes.  Special logic wired
399     // into the code generator will display the mangled name if it's
400     // present (and for AST_SymbolRef-s it'll use the mangled name of
401     // the AST_SymbolDeclaration that it points to).
402     var lname = -1;
403     var to_mangle = [];
404
405     if (options.cache) {
406         this.globals.each(function(symbol){
407             if (options.except.indexOf(symbol.name) < 0) {
408                 to_mangle.push(symbol);
409             }
410         });
411     }
412
413     var tw = new TreeWalker(function(node, descend){
414         if (node instanceof AST_LabeledStatement) {
415             // lname is incremented when we get to the AST_Label
416             var save_nesting = lname;
417             descend();
418             lname = save_nesting;
419             return true;        // don't descend again in TreeWalker
420         }
421         if (node instanceof AST_Scope) {
422             var p = tw.parent(), a = [];
423             node.variables.each(function(symbol){
424                 if (options.except.indexOf(symbol.name) < 0) {
425                     a.push(symbol);
426                 }
427             });
428             to_mangle.push.apply(to_mangle, a);
429             return;
430         }
431         if (node instanceof AST_Label) {
432             var name;
433             do name = base54(++lname); while (!is_identifier(name));
434             node.mangled_name = name;
435             return true;
436         }
437         if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
438             to_mangle.push(node.definition());
439             return;
440         }
441     });
442     this.walk(tw);
443     to_mangle.forEach(function(def){ def.mangle(options) });
444
445     if (options.cache) {
446         options.cache.cname = this.cname;
447     }
448 });
449
450 AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
451     options = this._default_mangler_options(options);
452     var tw = new TreeWalker(function(node){
453         if (node instanceof AST_Constant)
454             base54.consider(node.print_to_string());
455         else if (node instanceof AST_Return)
456             base54.consider("return");
457         else if (node instanceof AST_Throw)
458             base54.consider("throw");
459         else if (node instanceof AST_Continue)
460             base54.consider("continue");
461         else if (node instanceof AST_Break)
462             base54.consider("break");
463         else if (node instanceof AST_Debugger)
464             base54.consider("debugger");
465         else if (node instanceof AST_Directive)
466             base54.consider(node.value);
467         else if (node instanceof AST_While)
468             base54.consider("while");
469         else if (node instanceof AST_Do)
470             base54.consider("do while");
471         else if (node instanceof AST_If) {
472             base54.consider("if");
473             if (node.alternative) base54.consider("else");
474         }
475         else if (node instanceof AST_Var)
476             base54.consider("var");
477         else if (node instanceof AST_Const)
478             base54.consider("const");
479         else if (node instanceof AST_Lambda)
480             base54.consider("function");
481         else if (node instanceof AST_For)
482             base54.consider("for");
483         else if (node instanceof AST_ForIn)
484             base54.consider("for in");
485         else if (node instanceof AST_Switch)
486             base54.consider("switch");
487         else if (node instanceof AST_Case)
488             base54.consider("case");
489         else if (node instanceof AST_Default)
490             base54.consider("default");
491         else if (node instanceof AST_With)
492             base54.consider("with");
493         else if (node instanceof AST_ObjectSetter)
494             base54.consider("set" + node.key);
495         else if (node instanceof AST_ObjectGetter)
496             base54.consider("get" + node.key);
497         else if (node instanceof AST_ObjectKeyVal)
498             base54.consider(node.key);
499         else if (node instanceof AST_New)
500             base54.consider("new");
501         else if (node instanceof AST_This)
502             base54.consider("this");
503         else if (node instanceof AST_Try)
504             base54.consider("try");
505         else if (node instanceof AST_Catch)
506             base54.consider("catch");
507         else if (node instanceof AST_Finally)
508             base54.consider("finally");
509         else if (node instanceof AST_Symbol && node.unmangleable(options))
510             base54.consider(node.name);
511         else if (node instanceof AST_Unary || node instanceof AST_Binary)
512             base54.consider(node.operator);
513         else if (node instanceof AST_Dot)
514             base54.consider(node.property);
515     });
516     this.walk(tw);
517     base54.sort();
518 });
519
520 var base54 = (function() {
521     var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
522     var chars, frequency;
523     function reset() {
524         frequency = Object.create(null);
525         chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
526         chars.forEach(function(ch){ frequency[ch] = 0 });
527     }
528     base54.consider = function(str){
529         for (var i = str.length; --i >= 0;) {
530             var code = str.charCodeAt(i);
531             if (code in frequency) ++frequency[code];
532         }
533     };
534     base54.sort = function() {
535         chars = mergeSort(chars, function(a, b){
536             if (is_digit(a) && !is_digit(b)) return 1;
537             if (is_digit(b) && !is_digit(a)) return -1;
538             return frequency[b] - frequency[a];
539         });
540     };
541     base54.reset = reset;
542     reset();
543     base54.get = function(){ return chars };
544     base54.freq = function(){ return frequency };
545     function base54(num) {
546         var ret = "", base = 54;
547         num++;
548         do {
549             num--;
550             ret += String.fromCharCode(chars[num % base]);
551             num = Math.floor(num / base);
552             base = 64;
553         } while (num > 0);
554         return ret;
555     };
556     return base54;
557 })();
558
559 AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
560     options = defaults(options, {
561         undeclared       : false, // this makes a lot of noise
562         unreferenced     : true,
563         assign_to_global : true,
564         func_arguments   : true,
565         nested_defuns    : true,
566         eval             : true
567     });
568     var tw = new TreeWalker(function(node){
569         if (options.undeclared
570             && node instanceof AST_SymbolRef
571             && node.undeclared())
572         {
573             // XXX: this also warns about JS standard names,
574             // i.e. Object, Array, parseInt etc.  Should add a list of
575             // exceptions.
576             AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
577                 name: node.name,
578                 file: node.start.file,
579                 line: node.start.line,
580                 col: node.start.col
581             });
582         }
583         if (options.assign_to_global)
584         {
585             var sym = null;
586             if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
587                 sym = node.left;
588             else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
589                 sym = node.init;
590             if (sym
591                 && (sym.undeclared()
592                     || (sym.global() && sym.scope !== sym.definition().scope))) {
593                 AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
594                     msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
595                     name: sym.name,
596                     file: sym.start.file,
597                     line: sym.start.line,
598                     col: sym.start.col
599                 });
600             }
601         }
602         if (options.eval
603             && node instanceof AST_SymbolRef
604             && node.undeclared()
605             && node.name == "eval") {
606             AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
607         }
608         if (options.unreferenced
609             && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
610             && !(node instanceof AST_SymbolCatch)
611             && node.unreferenced()) {
612             AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
613                 type: node instanceof AST_Label ? "Label" : "Symbol",
614                 name: node.name,
615                 file: node.start.file,
616                 line: node.start.line,
617                 col: node.start.col
618             });
619         }
620         if (options.func_arguments
621             && node instanceof AST_Lambda
622             && node.uses_arguments) {
623             AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
624                 name: node.name ? node.name.name : "anonymous",
625                 file: node.start.file,
626                 line: node.start.line,
627                 col: node.start.col
628             });
629         }
630         if (options.nested_defuns
631             && node instanceof AST_Defun
632             && !(tw.parent() instanceof AST_Scope)) {
633             AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", {
634                 name: node.name.name,
635                 type: tw.parent().TYPE,
636                 file: node.start.file,
637                 line: node.start.line,
638                 col: node.start.col
639             });
640         }
641     });
642     this.walk(tw);
643 });