aboutsummaryrefslogtreecommitdiff
path: root/node_modules/uglify-js/lib/scope.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-08-14 05:01:11 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-08-14 05:02:09 +0200
commit363723fc84f7b8477592e0105aeb331ec9a017af (patch)
tree29f92724f34131bac64d6a318dd7e30612e631c7 /node_modules/uglify-js/lib/scope.js
parent5634e77ad96bfe1818f6b6ee70b7379652e5487f (diff)
node_modules
Diffstat (limited to 'node_modules/uglify-js/lib/scope.js')
-rw-r--r--node_modules/uglify-js/lib/scope.js289
1 files changed, 79 insertions, 210 deletions
diff --git a/node_modules/uglify-js/lib/scope.js b/node_modules/uglify-js/lib/scope.js
index bf6dbcbbf..df7b2076c 100644
--- a/node_modules/uglify-js/lib/scope.js
+++ b/node_modules/uglify-js/lib/scope.js
@@ -76,10 +76,10 @@ SymbolDef.prototype = {
else if (!this.mangled_name && !this.unmangleable(options)) {
var s = this.scope;
var sym = this.orig[0];
- if (!options.screw_ie8 && sym instanceof AST_SymbolLambda)
+ if (options.ie8 && sym instanceof AST_SymbolLambda)
s = s.parent_scope;
var def;
- if (this.defun && (def = this.defun.variables.get(this.name))) {
+ if (def = this.redefined()) {
this.mangled_name = def.mangled_name || def.name;
} else
this.mangled_name = s.next_mangled(options, this);
@@ -87,13 +87,16 @@ SymbolDef.prototype = {
cache.set(this.name, this.mangled_name);
}
}
+ },
+ redefined: function() {
+ return this.defun && this.defun.variables.get(this.name);
}
};
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
options = defaults(options, {
cache: null,
- screw_ie8: true,
+ ie8: false,
});
// pass 1: setup scope chaining and handle definitions
@@ -156,8 +159,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
// later.
(node.scope = defun.parent_scope).def_function(node);
}
- else if (node instanceof AST_SymbolVar
- || node instanceof AST_SymbolConst) {
+ else if (node instanceof AST_SymbolVar) {
defun.def_variable(node);
if (defun !== scope) {
node.mark_enclosed(options);
@@ -184,16 +186,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
self.walk(tw);
// pass 2: find back references and eval
- var func = null;
- var globals = self.globals = new Dictionary();
+ self.globals = new Dictionary();
var tw = new TreeWalker(function(node, descend){
- if (node instanceof AST_Lambda) {
- var prev_func = func;
- func = node;
- descend();
- func = prev_func;
- return true;
- }
if (node instanceof AST_LoopControl && node.label) {
node.label.thedef.references.push(node);
return true;
@@ -206,21 +200,30 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
}
}
var sym = node.scope.find_variable(name);
- if (node.scope instanceof AST_Lambda && name == "arguments") {
- node.scope.uses_arguments = true;
- }
if (!sym) {
sym = self.def_global(node);
+ } else if (sym.scope instanceof AST_Lambda && name == "arguments") {
+ sym.scope.uses_arguments = true;
}
node.thedef = sym;
node.reference(options);
return true;
}
+ // ensure mangling works if catch reuses a scope variable
+ var def;
+ if (node instanceof AST_SymbolCatch && (def = node.definition().redefined())) {
+ var s = node.scope;
+ while (s) {
+ push_uniq(s.enclosed, def);
+ if (s === def.scope) break;
+ s = s.parent_scope;
+ }
+ }
});
self.walk(tw);
// pass 3: fix up any scoping issue with IE8
- if (!options.screw_ie8) {
+ if (options.ie8) {
self.walk(new TreeWalker(function(node, descend) {
if (node instanceof AST_SymbolCatch) {
var name = node.name;
@@ -268,7 +271,7 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
this.uses_arguments = false;
- this.def_variable(new AST_SymbolVar({
+ this.def_variable(new AST_SymbolFunarg({
name: "arguments",
start: this.start,
end: this.end
@@ -325,8 +328,8 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
if (!is_identifier(m)) continue; // skip over "do"
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
- // shadow a name excepted from mangling.
- if (options.except.indexOf(m) >= 0) continue;
+ // shadow a name reserved from mangling.
+ if (options.reserved.indexOf(m) >= 0) continue;
// we must ensure that the mangled name does not shadow a name
// from some parent scope that is referenced in this or in
@@ -358,31 +361,18 @@ AST_Function.DEFMETHOD("next_mangled", function(options, def){
});
AST_Symbol.DEFMETHOD("unmangleable", function(options){
- return this.definition().unmangleable(options);
+ var def = this.definition();
+ return !def || def.unmangleable(options);
});
// labels are always mangleable
-AST_Label.DEFMETHOD("unmangleable", function(){
- return false;
-});
+AST_Label.DEFMETHOD("unmangleable", return_false);
AST_Symbol.DEFMETHOD("unreferenced", function(){
return this.definition().references.length == 0
&& !(this.scope.uses_eval || this.scope.uses_with);
});
-AST_Symbol.DEFMETHOD("undeclared", function(){
- return this.definition().undeclared;
-});
-
-AST_LabelRef.DEFMETHOD("undeclared", function(){
- return false;
-});
-
-AST_Label.DEFMETHOD("undeclared", function(){
- return false;
-});
-
AST_Symbol.DEFMETHOD("definition", function(){
return this.thedef;
});
@@ -392,21 +382,22 @@ AST_Symbol.DEFMETHOD("global", function(){
});
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
- return defaults(options, {
+ options = defaults(options, {
eval : false,
- except : [],
+ ie8 : false,
keep_fnames : false,
- screw_ie8 : true,
- sort : false, // Ignored. Flag retained for backwards compatibility.
+ reserved : [],
toplevel : false,
});
+ if (!Array.isArray(options.reserved)) options.reserved = [];
+ return options;
});
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
options = this._default_mangler_options(options);
// Never mangle arguments
- options.except.push('arguments');
+ options.reserved.push('arguments');
// We only need to mangle declaration nodes. Special logic wired
// into the code generator will display the mangled name if it's
@@ -417,7 +408,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
if (options.cache) {
this.globals.each(function(symbol){
- if (options.except.indexOf(symbol.name) < 0) {
+ if (options.reserved.indexOf(symbol.name) < 0) {
to_mangle.push(symbol);
}
});
@@ -434,7 +425,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
if (node instanceof AST_Scope) {
var p = tw.parent(), a = [];
node.variables.each(function(symbol){
- if (options.except.indexOf(symbol.name) < 0) {
+ if (options.reserved.indexOf(symbol.name) < 0) {
a.push(symbol);
}
});
@@ -447,7 +438,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
node.mangled_name = name;
return true;
}
- if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
+ if (!options.ie8 && node instanceof AST_SymbolCatch) {
to_mangle.push(node.definition());
return;
}
@@ -462,105 +453,69 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
options = this._default_mangler_options(options);
- var tw = new TreeWalker(function(node){
- if (node instanceof AST_Constant)
- base54.consider(node.print_to_string());
- else if (node instanceof AST_Return)
- base54.consider("return");
- else if (node instanceof AST_Throw)
- base54.consider("throw");
- else if (node instanceof AST_Continue)
- base54.consider("continue");
- else if (node instanceof AST_Break)
- base54.consider("break");
- else if (node instanceof AST_Debugger)
- base54.consider("debugger");
- else if (node instanceof AST_Directive)
- base54.consider(node.value);
- else if (node instanceof AST_While)
- base54.consider("while");
- else if (node instanceof AST_Do)
- base54.consider("do while");
- else if (node instanceof AST_If) {
- base54.consider("if");
- if (node.alternative) base54.consider("else");
- }
- else if (node instanceof AST_Var)
- base54.consider("var");
- else if (node instanceof AST_Const)
- base54.consider("const");
- else if (node instanceof AST_Lambda)
- base54.consider("function");
- else if (node instanceof AST_For)
- base54.consider("for");
- else if (node instanceof AST_ForIn)
- base54.consider("for in");
- else if (node instanceof AST_Switch)
- base54.consider("switch");
- else if (node instanceof AST_Case)
- base54.consider("case");
- else if (node instanceof AST_Default)
- base54.consider("default");
- else if (node instanceof AST_With)
- base54.consider("with");
- else if (node instanceof AST_ObjectSetter)
- base54.consider("set" + node.key);
- else if (node instanceof AST_ObjectGetter)
- base54.consider("get" + node.key);
- else if (node instanceof AST_ObjectKeyVal)
- base54.consider(node.key);
- else if (node instanceof AST_New)
- base54.consider("new");
- else if (node instanceof AST_This)
- base54.consider("this");
- else if (node instanceof AST_Try)
- base54.consider("try");
- else if (node instanceof AST_Catch)
- base54.consider("catch");
- else if (node instanceof AST_Finally)
- base54.consider("finally");
- else if (node instanceof AST_Symbol && node.unmangleable(options))
- base54.consider(node.name);
- else if (node instanceof AST_Unary || node instanceof AST_Binary)
- base54.consider(node.operator);
- else if (node instanceof AST_Dot)
- base54.consider(node.property);
- });
- this.walk(tw);
+ try {
+ AST_Node.prototype.print = function(stream, force_parens) {
+ this._print(stream, force_parens);
+ if (this instanceof AST_Symbol && !this.unmangleable(options)) {
+ base54.consider(this.name, -1);
+ } else if (options.properties) {
+ if (this instanceof AST_Dot) {
+ base54.consider(this.property, -1);
+ } else if (this instanceof AST_Sub) {
+ skip_string(this.property);
+ }
+ }
+ };
+ base54.consider(this.print_to_string(), 1);
+ } finally {
+ AST_Node.prototype.print = AST_Node.prototype._print;
+ }
base54.sort();
+
+ function skip_string(node) {
+ if (node instanceof AST_String) {
+ base54.consider(node.value, -1);
+ } else if (node instanceof AST_Conditional) {
+ skip_string(node.consequent);
+ skip_string(node.alternative);
+ } else if (node instanceof AST_Sequence) {
+ skip_string(node.expressions[node.expressions.length - 1]);
+ }
+ }
});
var base54 = (function() {
- var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
+ var leading = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_".split("");
+ var digits = "0123456789".split("");
var chars, frequency;
function reset() {
frequency = Object.create(null);
- chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
- chars.forEach(function(ch){ frequency[ch] = 0 });
+ leading.forEach(function(ch) {
+ frequency[ch] = 0;
+ });
+ digits.forEach(function(ch) {
+ frequency[ch] = 0;
+ });
}
- base54.consider = function(str){
+ base54.consider = function(str, delta) {
for (var i = str.length; --i >= 0;) {
- var code = str.charCodeAt(i);
- if (code in frequency) ++frequency[code];
+ frequency[str[i]] += delta;
}
};
+ function compare(a, b) {
+ return frequency[b] - frequency[a];
+ }
base54.sort = function() {
- chars = mergeSort(chars, function(a, b){
- if (is_digit(a) && !is_digit(b)) return 1;
- if (is_digit(b) && !is_digit(a)) return -1;
- return frequency[b] - frequency[a];
- });
+ chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
};
base54.reset = reset;
reset();
- base54.get = function(){ return chars };
- base54.freq = function(){ return frequency };
function base54(num) {
var ret = "", base = 54;
num++;
do {
num--;
- ret += String.fromCharCode(chars[num % base]);
+ ret += chars[num % base];
num = Math.floor(num / base);
base = 64;
} while (num > 0);
@@ -568,89 +523,3 @@ var base54 = (function() {
};
return base54;
})();
-
-AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
- options = defaults(options, {
- assign_to_global : true,
- eval : true,
- func_arguments : true,
- nested_defuns : true,
- undeclared : false, // this makes a lot of noise
- unreferenced : true,
- });
- var tw = new TreeWalker(function(node){
- if (options.undeclared
- && node instanceof AST_SymbolRef
- && node.undeclared())
- {
- // XXX: this also warns about JS standard names,
- // i.e. Object, Array, parseInt etc. Should add a list of
- // exceptions.
- AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
- name: node.name,
- file: node.start.file,
- line: node.start.line,
- col: node.start.col
- });
- }
- if (options.assign_to_global)
- {
- var sym = null;
- if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
- sym = node.left;
- else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
- sym = node.init;
- if (sym
- && (sym.undeclared()
- || (sym.global() && sym.scope !== sym.definition().scope))) {
- AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
- msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
- name: sym.name,
- file: sym.start.file,
- line: sym.start.line,
- col: sym.start.col
- });
- }
- }
- if (options.eval
- && node instanceof AST_SymbolRef
- && node.undeclared()
- && node.name == "eval") {
- AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
- }
- if (options.unreferenced
- && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
- && !(node instanceof AST_SymbolCatch)
- && node.unreferenced()) {
- AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
- type: node instanceof AST_Label ? "Label" : "Symbol",
- name: node.name,
- file: node.start.file,
- line: node.start.line,
- col: node.start.col
- });
- }
- if (options.func_arguments
- && node instanceof AST_Lambda
- && node.uses_arguments) {
- AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
- name: node.name ? node.name.name : "anonymous",
- file: node.start.file,
- line: node.start.line,
- col: node.start.col
- });
- }
- if (options.nested_defuns
- && node instanceof AST_Defun
- && !(tw.parent() instanceof AST_Scope)) {
- AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", {
- name: node.name.name,
- type: tw.parent().TYPE,
- file: node.start.file,
- line: node.start.line,
- col: node.start.col
- });
- }
- });
- this.walk(tw);
-});