aboutsummaryrefslogtreecommitdiff
path: root/node_modules/uglify-js/lib/scope.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/uglify-js/lib/scope.js')
-rw-r--r--node_modules/uglify-js/lib/scope.js107
1 files changed, 85 insertions, 22 deletions
diff --git a/node_modules/uglify-js/lib/scope.js b/node_modules/uglify-js/lib/scope.js
index 8e766a567..bbfa037cd 100644
--- a/node_modules/uglify-js/lib/scope.js
+++ b/node_modules/uglify-js/lib/scope.js
@@ -43,15 +43,16 @@
"use strict";
-function SymbolDef(scope, index, orig) {
+function SymbolDef(scope, orig) {
this.name = orig.name;
this.orig = [ orig ];
+ this.eliminated = 0;
this.scope = scope;
this.references = [];
+ this.replaced = 0;
this.global = false;
this.mangled_name = null;
this.undeclared = false;
- this.index = index;
this.id = SymbolDef.next_id++;
};
@@ -251,7 +252,7 @@ AST_Toplevel.DEFMETHOD("def_global", function(node){
if (globals.has(name)) {
return globals.get(name);
} else {
- var g = new SymbolDef(this, globals.size(), node);
+ var g = new SymbolDef(this, node);
g.undeclared = true;
g.global = true;
globals.set(name, g);
@@ -312,7 +313,7 @@ AST_Scope.DEFMETHOD("def_function", function(symbol){
AST_Scope.DEFMETHOD("def_variable", function(symbol){
var def;
if (!this.variables.has(symbol.name)) {
- def = new SymbolDef(this, this.variables.size(), symbol);
+ def = new SymbolDef(this, symbol);
this.variables.set(symbol.name, def);
def.global = !this.parent_scope;
} else {
@@ -330,7 +331,7 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
// shadow a name reserved from mangling.
- if (options.reserved.indexOf(m) >= 0) continue;
+ if (member(m, options.reserved)) continue;
// we must ensure that the mangled name does not shadow a name
// from some parent scope that is referenced in this or in
@@ -382,7 +383,7 @@ AST_Symbol.DEFMETHOD("global", function(){
return this.definition().global;
});
-AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
+AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
options = defaults(options, {
eval : false,
ie8 : false,
@@ -391,15 +392,14 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
toplevel : false,
});
if (!Array.isArray(options.reserved)) options.reserved = [];
+ // Never mangle arguments
+ push_uniq(options.reserved, "arguments");
return options;
});
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
options = this._default_mangler_options(options);
- // Never mangle 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
// present (and for AST_SymbolRef-s it'll use the mangled name of
@@ -408,11 +408,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
var to_mangle = [];
if (options.cache) {
- this.globals.each(function(symbol){
- if (options.reserved.indexOf(symbol.name) < 0) {
- to_mangle.push(symbol);
- }
- });
+ this.globals.each(collect);
}
var tw = new TreeWalker(function(node, descend){
@@ -424,13 +420,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
return true; // don't descend again in TreeWalker
}
if (node instanceof AST_Scope) {
- var p = tw.parent(), a = [];
- node.variables.each(function(symbol){
- if (options.reserved.indexOf(symbol.name) < 0) {
- a.push(symbol);
- }
- });
- to_mangle.push.apply(to_mangle, a);
+ node.variables.each(collect);
return;
}
if (node instanceof AST_Label) {
@@ -450,6 +440,79 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
if (options.cache) {
options.cache.cname = this.cname;
}
+
+ function collect(symbol) {
+ if (!member(symbol.name, options.reserved)) {
+ to_mangle.push(symbol);
+ }
+ }
+});
+
+AST_Toplevel.DEFMETHOD("find_unique_prefix", function(options) {
+ var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
+ var cache = options.cache && options.cache.props;
+ var prefixes = Object.create(null);
+ options.reserved.forEach(add_prefix);
+ this.globals.each(add_def);
+ this.walk(new TreeWalker(function(node) {
+ if (node instanceof AST_Scope) node.variables.each(add_def);
+ if (node instanceof AST_SymbolCatch) add_def(node.definition());
+ }));
+ var prefix, i = 0;
+ do {
+ prefix = create_name(i++);
+ } while (prefixes[prefix]);
+ return prefix;
+
+ function add_prefix(name) {
+ if (/[0-9]$/.test(name)) {
+ prefixes[name.replace(/[0-9]+$/, "")] = true;
+ }
+ }
+
+ function add_def(def) {
+ var name = def.name;
+ if (def.global && cache && cache.has(name)) name = cache.get(name);
+ else if (!def.unmangleable(options)) return;
+ add_prefix(name);
+ }
+
+ function create_name(num) {
+ var name = "";
+ do {
+ name += letters[num % letters.length];
+ num = Math.floor(num / letters.length);
+ } while (num);
+ return name;
+ }
+});
+
+AST_Toplevel.DEFMETHOD("expand_names", function(options) {
+ options = this._default_mangler_options(options);
+ var prefix = this.find_unique_prefix(options);
+ this.globals.each(rename);
+ this.walk(new TreeWalker(function(node) {
+ if (node instanceof AST_Scope) node.variables.each(rename);
+ if (node instanceof AST_SymbolCatch) rename(node.definition());
+ }));
+
+ function rename(def) {
+ if (def.global || def.unmangleable(options)) return;
+ if (member(def.name, options.reserved)) return;
+ var d = def.redefined();
+ def.name = d ? d.name : prefix + def.id;
+ def.orig.forEach(function(sym) {
+ sym.name = def.name;
+ });
+ def.references.forEach(function(sym) {
+ sym.name = def.name;
+ });
+ }
+});
+
+AST_Node.DEFMETHOD("tail_node", return_this);
+AST_Sequence.DEFMETHOD("tail_node", function() {
+ return this.expressions[this.expressions.length - 1];
});
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
@@ -480,7 +543,7 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
skip_string(node.consequent);
skip_string(node.alternative);
} else if (node instanceof AST_Sequence) {
- skip_string(node.expressions[node.expressions.length - 1]);
+ skip_string(node.tail_node());
}
}
});