Permalink
Browse files

Update the UglifyJS code.

  • Loading branch information...
1 parent c0d9939 commit f4b5d3fc51cfb2b62f182e88b85386b4456c080d @jeresig jeresig committed May 2, 2011
Showing with 222 additions and 90 deletions.
  1. +18 −22 build/lib/parse-js.js
  2. +73 −23 build/lib/process.js
  3. +131 −45 build/uglify.js
View
@@ -751,14 +751,17 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);
};
- var statement = embed_tokens ? function() {
- var start = S.token;
- var ast = $statement.apply(this, arguments);
- ast[0] = add_tokens(ast[0], start, prev());
- return ast;
- } : $statement;
-
- function $statement() {
+ function maybe_embed_tokens(parser) {
+ if (embed_tokens) return function() {
+ var start = S.token;
+ var ast = parser.apply(this, arguments);
+ ast[0] = add_tokens(ast[0], start, prev());
+ return ast;
+ };
+ else return parser;
+ };
+
+ var statement = maybe_embed_tokens(function() {
if (is("operator", "/")) {
S.peeked = null;
S.token = S.input(true); // force regexp
@@ -852,7 +855,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
unexpected();
}
}
- };
+ });
function labeled_statement(label) {
S.labels.push(label);
@@ -910,14 +913,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return as("for-in", init, lhs, obj, in_loop(statement));
};
- var function_ = embed_tokens ? function() {
- var start = prev();
- var ast = $function_.apply(this, arguments);
- ast[0] = add_tokens(ast[0], start, prev());
- return ast;
- } : $function_;
-
- function $function_(in_statement) {
+ var function_ = maybe_embed_tokens(function(in_statement) {
var name = is("name") ? prog1(S.token.value, next) : null;
if (in_statement && !name)
unexpected();
@@ -945,7 +941,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
S.in_loop = loop;
return a;
})());
- };
+ });
function if_() {
var cond = parenthesised(), body = statement(), belse;
@@ -1053,7 +1049,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return subscripts(as("new", newexp, args), true);
};
- function expr_atom(allow_calls) {
+ var expr_atom = maybe_embed_tokens(function(allow_calls) {
if (is("operator", "new")) {
next();
return new_();
@@ -1088,7 +1084,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return subscripts(prog1(atom, next), allow_calls);
}
unexpected();
- };
+ });
function expr_list(closing, allow_trailing_comma, allow_empty) {
var first = true, a = [];
@@ -1228,7 +1224,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return left;
};
- function expression(commas, no_in) {
+ var expression = maybe_embed_tokens(function(commas, no_in) {
if (arguments.length == 0)
commas = true;
var expr = maybe_assign(no_in);
@@ -1237,7 +1233,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return as("seq", expr, expression(true, no_in));
}
return expr;
- };
+ });
function in_loop(cont) {
try {
View
@@ -75,6 +75,12 @@ function ast_walker(ast) {
return a;
}) ];
};
+ function _block(statements) {
+ var out = [ this[0] ];
+ if (statements != null)
+ out.push(MAP(statements, walk));
+ return out;
+ };
var walkers = {
"string": function(str) {
return [ this[0], str ];
@@ -88,12 +94,8 @@ function ast_walker(ast) {
"toplevel": function(statements) {
return [ this[0], MAP(statements, walk) ];
},
- "block": function(statements) {
- var out = [ this[0] ];
- if (statements != null)
- out.push(MAP(statements, walk));
- return out;
- },
+ "block": _block,
+ "splice": _block,
"var": _vardefs,
"const": _vardefs,
"try": function(t, c, f) {
@@ -377,7 +379,9 @@ function ast_add_scope(ast) {
};
function _lambda(name, args, body) {
- return [ this[0], this[0] == "defun" ? define(name) : name, args, with_new_scope(function(){
+ var is_defun = this[0] == "defun";
+ return [ this[0], is_defun ? define(name) : name, args, with_new_scope(function(){
+ if (!is_defun) define(name);
MAP(args, define);
return MAP(body, walk);
})];
@@ -463,9 +467,22 @@ function ast_mangle(ast, options) {
return scope.get_mangled(name, newMangle);
};
+ function get_define(name) {
+ // we always lookup a defined symbol for the current scope FIRST, so declared
+ // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value
+ if (!scope.has(name)) {
+ if (HOP(options.defines, name)) {
+ return options.defines[name];
+ }
+ }
+ return null;
+ };
+
function _lambda(name, args, body) {
- if (name) name = get_mangled(name);
+ var is_defun = this[0] == "defun";
+ if (is_defun && name) name = get_mangled(name);
body = with_scope(body.scope, function(){
+ if (!is_defun && name) name = get_mangled(name);
args = MAP(args, function(name){ return get_mangled(name) });
return MAP(body, walk);
});
@@ -507,7 +524,7 @@ function ast_mangle(ast, options) {
"var": _vardefs,
"const": _vardefs,
"name": function(name) {
- return [ this[0], get_mangled(name) ];
+ return get_define(name) || [ this[0], get_mangled(name) ];
},
"try": function(t, c, f) {
return [ this[0],
@@ -583,11 +600,18 @@ function boolean_expr(expr) {
};
function make_conditional(c, t, e) {
+ var make_real_conditional = function() {
if (c[0] == "unary-prefix" && c[1] == "!") {
- return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
+ return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
} else {
- return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ];
+ return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ];
}
+ };
+ // shortcut the conditional if the expression has a constant value
+ return when_constant(c, function(ast, val){
+ warn_unreachable(val ? e : t);
+ return (val ? t : e);
+ }, make_real_conditional);
};
function empty(b) {
@@ -676,6 +700,18 @@ var when_constant = (function(){
|| (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {
expr[1] = expr[1].substr(0, 2);
}
+ else if (no && expr[0] == "binary"
+ && (expr[1] == "||" || expr[1] == "&&")) {
+ // the whole expression is not constant but the lval may be...
+ try {
+ var lval = evaluate(expr[2]);
+ expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) ||
+ (expr[1] == "||" && (lval ? lval : expr[3])) ||
+ expr);
+ } catch(ex2) {
+ // IGNORE... lval is not constant
+ }
+ }
return no ? no.call(expr, expr) : null;
}
else throw ex;
@@ -751,9 +787,14 @@ function ast_squeeze(ast, options) {
};
function _lambda(name, args, body) {
- return [ this[0], name, args, with_scope(body.scope, function(){
- return tighten(MAP(body, walk), "lambda");
- }) ];
+ var is_defun = this[0] == "defun";
+ body = with_scope(body.scope, function(){
+ var ret = tighten(MAP(body, walk), "lambda");
+ if (!is_defun && name && !HOP(scope.refs, name))
+ name = null;
+ return ret;
+ });
+ return [ this[0], name, args, body ];
};
// we get here for blocks that have been already transformed.
@@ -959,13 +1000,7 @@ function ast_squeeze(ast, options) {
return [ branch[0] ? walk(branch[0]) : null, block ];
}) ];
},
- "function": function() {
- var ret = _lambda.apply(this, arguments);
- if (ret[1] && !HOP(scope.refs, ret[1])) {
- ret[1] = null;
- }
- return ret;
- },
+ "function": _lambda,
"defun": _lambda,
"block": function(body) {
if (body) return rmblock([ "block", tighten(MAP(body, walk)) ]);
@@ -1067,6 +1102,8 @@ function to_ascii(str) {
});
};
+var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]);
+
function gen_code(ast, options) {
options = defaults(options, {
indent_start : 0,
@@ -1197,6 +1234,19 @@ function gen_code(ast, options) {
return make_block_statements(statements)
.join(newline + newline);
},
+ "splice": function(statements) {
+ var parent = $stack[$stack.length - 2][0];
+ if (HOP(SPLICE_NEEDS_BRACKETS, parent)) {
+ // we need block brackets in this case
+ return make_block.apply(this, arguments);
+ } else {
+ return MAP(make_block_statements(statements, true),
+ function(line, i) {
+ // the first line is already indented
+ return i > 0 ? indent(line) : line;
+ }).join(newline);
+ }
+ },
"block": make_block,
"var": function(defs) {
return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
@@ -1437,7 +1487,7 @@ function gen_code(ast, options) {
return add_spaces([ out, make_block(body) ]);
};
- function make_block_statements(statements) {
+ function make_block_statements(statements, noindent) {
for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {
var stat = statements[i];
var code = make(stat);
@@ -1455,7 +1505,7 @@ function gen_code(ast, options) {
a.push(code);
}
}
- return MAP(a, indent);
+ return noindent ? a : MAP(a, indent);
};
function make_switch_block(body) {
Oops, something went wrong.

0 comments on commit f4b5d3f

Please sign in to comment.