uglifier 0.5.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of uglifier might be problematic. Click here for more details.

data/.gitmodules CHANGED
@@ -1,3 +1,3 @@
1
1
  [submodule "vendor/uglifyjs"]
2
2
  path = vendor/uglifyjs
3
- url = http://github.com/mishoo/UglifyJS.git
3
+ url = http://github.com/lautis/UglifyJS.git
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ env: "EXECJS_RUNTIME='RubyRacer'"
5
+ before_script: "git submodule update --init --recursive"
data/Gemfile CHANGED
@@ -1,16 +1,25 @@
1
1
  source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
5
2
 
6
3
  gem "execjs", ">=0.3.0"
7
4
  gem "multi_json", ">= 1.0.2"
8
5
 
9
- # Add dependencies to develop your gem here.
10
- # Include everything needed to run rake, tests, features, etc.
6
+ # Depend on defined ExecJS runtime
7
+ execjs_runtimes = {
8
+ "RubyRacer" => "therubyracer",
9
+ "RubyRhino" => "therubyrhino",
10
+ "Mustang" => "mustang"
11
+ }
12
+
13
+ if ENV["EXECJS_RUNTIME"] && execjs_runtimes[ENV["EXECJS_RUNTIME"]]
14
+ gem execjs_runtimes[ENV["EXECJS_RUNTIME"]], :group => :development
15
+ end
16
+
17
+ # Engine
18
+ gem ENV["MULTI_JSON_ENGINE"], :group => :development if ENV["MULTI_JSON_ENGINE"]
19
+
11
20
  group :development do
12
- gem "rspec", "~> 2.5.0"
21
+ gem "rspec", "~> 2.6.0"
13
22
  gem "bundler", "~> 1.0.0"
14
- gem "jeweler", "~> 1.5.0"
23
+ gem "jeweler", "~> 1.6.0"
15
24
  gem "rcov", ">= 0"
16
25
  end
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Ville Lautanala
1
+ Copyright (c) 2011 Ville Lautanala
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Ruby wrapper for UglifyJS[https://github.com/mishoo/UglifyJS] JavaScript compressor.
4
4
 
5
+ http://travis-ci.org/lautis/uglifier.png
6
+
5
7
  == Installation
6
8
 
7
9
  Uglifier is available as ruby gem.
@@ -17,27 +19,41 @@ Ensure that your environment has a JavaScript interpreter supported by ExecJS[ht
17
19
  Uglifier.new.compile(File.read("source.js"))
18
20
  # => js file minified
19
21
 
22
+ # Or alternatively
23
+ Uglifier.compile(File.read("source.js"))
24
+
20
25
  When initializing UglifyJS, you can tune the behavior of UglifyJS by passing options. For example, if you want top-level variable names to be mangled:
21
26
 
22
27
  Uglifier.new(:toplevel => true).compile(source)
23
28
 
24
- Defaults are
29
+ # Or
30
+ Uglifier.compile(source, :toplevel => true)
25
31
 
32
+ Available options and their defaults are
26
33
  {
27
34
  :mangle => true, # Mangle variables names
28
35
  :toplevel => false, # Mangle top-level variable names
36
+ :except => [], # Variable names to be excluded from mangling
37
+ :max_line_length => 32 * 1024, # Maximum line length
29
38
  :squeeze => true, # Squeeze code resulting in smaller, but less-readable code
30
39
  :seqs => true, # Reduce consecutive statements in blocks into single statement
31
40
  :dead_code => true, # Remove dead code (e.g. after return)
41
+ :unsafe => false, # Optimizations known to be unsafe in some situations
42
+ :copyright => true, # Show copyright message
32
43
  :beautify => false, # Ouput indented code
33
44
  :beautify_options => {
34
45
  :indent_level => 4,
35
46
  :indent_start => 0,
36
47
  :quote_keys => false,
37
- :space_colon => 0
48
+ :space_colon => 0,
49
+ :ascii_only => false
38
50
  }
39
51
  }
40
52
 
53
+ == Submitting an issue
54
+
55
+ Uglifier uses the {GitHub issue tracker}[https://github.com/lautis/uglifier/issues] to track bugs and features. Before submitting a bug report or feature request, check to make sure it hasn't already been submitted. You can indicate support for an existing issuse by voting it up. When submitting a bug report, please include a Gist that includes a stack trace and any details that may be necessary to reproduce the bug, including your gem version, Ruby version, <b>MultiJSON engine</b> and <b>ExecJS runtime</b>. Ideally, a bug report should include a pull request with failing specs.
56
+
41
57
  == Contributing to uglifier
42
58
 
43
59
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
@@ -47,8 +63,3 @@ Defaults are
47
63
  * Commit and push until you are happy with your contribution
48
64
  * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
49
65
  * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
50
-
51
- == Copyright
52
-
53
- Copyright (c) 2010 Ville Lautanala. See LICENSE.txt for
54
- further details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.4
1
+ 1.0.0
data/lib/uglifier.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require "execjs"
2
4
  require "multi_json"
3
5
 
@@ -5,9 +7,12 @@ class Uglifier
5
7
  Error = ExecJS::Error
6
8
  # MultiJson.engine = :json_gem
7
9
 
10
+ # Default options for compilation
8
11
  DEFAULTS = {
9
12
  :mangle => true, # Mangle variables names
10
13
  :toplevel => false, # Mangle top-level variable names
14
+ :except => [], # Variable names to be excluded from mangling
15
+ :max_line_length => 32 * 1024, # Maximum line length
11
16
  :squeeze => true, # Squeeze code resulting in smaller, but less-readable code
12
17
  :seqs => true, # Reduce consecutive statements in blocks into single statement
13
18
  :dead_code => true, # Remove dead code (e.g. after return)
@@ -18,23 +23,37 @@ class Uglifier
18
23
  :indent_level => 4,
19
24
  :indent_start => 0,
20
25
  :quote_keys => false,
21
- :space_colon => 0
26
+ :space_colon => 0,
27
+ :ascii_only => false
22
28
  }
23
29
  }
24
30
 
25
31
  SourcePath = File.expand_path("../uglify.js", __FILE__)
26
32
  ES5FallbackPath = File.expand_path("../es5.js", __FILE__)
27
33
 
34
+ # Minifies JavaScript code using implicit context.
35
+ #
36
+ # source should be a String or IO object containing valid JavaScript.
37
+ # options contain optional overrides to Uglifier::DEFAULTS
38
+ #
39
+ # Returns minified code as String
28
40
  def self.compile(source, options = {})
29
41
  self.new(options).compile(source)
30
42
  end
31
43
 
32
- # Create new instance of Uglifier with given options
44
+ # Initialize new context for Uglifier with given options
45
+ #
46
+ # options - Hash of options to override Uglifier::DEFAULTS
33
47
  def initialize(options = {})
34
48
  @options = DEFAULTS.merge(options)
35
- @context = ExecJS.compile(File.read(ES5FallbackPath) + File.read(SourcePath))
49
+ @context = ExecJS.compile(File.open(ES5FallbackPath, "r:UTF-8").read + File.open(SourcePath, "r:UTF-8").read)
36
50
  end
37
51
 
52
+ # Minifies JavaScript code
53
+ #
54
+ # source should be a String or IO object containing valid JavaScript.
55
+ #
56
+ # Returns minified code as String
38
57
  def compile(source)
39
58
  source = source.respond_to?(:read) ? source.read : source.to_s
40
59
 
@@ -66,6 +85,11 @@ class Uglifier
66
85
  end
67
86
 
68
87
  js << "result += UglifyJS.uglify.gen_code(ast, #{MultiJson.encode(gen_code_options)});"
88
+
89
+ if !@options[:beautify] && @options[:max_line_length]
90
+ js << "result = UglifyJS.uglify.split_lines(result, #{@options[:max_line_length].to_i})"
91
+ end
92
+
69
93
  js << "return result;"
70
94
 
71
95
  @context.exec js.join("\n")
@@ -75,7 +99,11 @@ class Uglifier
75
99
  private
76
100
 
77
101
  def mangle_options
78
- @options[:toplevel]
102
+ {
103
+ "toplevel" => @options[:toplevel],
104
+ "defines" => {},
105
+ "except" => @options[:except]
106
+ }
79
107
  end
80
108
 
81
109
  def squeeze_options
@@ -87,6 +115,7 @@ class Uglifier
87
115
  end
88
116
 
89
117
  def gen_code_options
90
- @options[:beautify] ? @options[:beautify_options] : {}
118
+
119
+ @options[:beautify] ? {:beautify => true}.merge(@options[:beautify_options]) : {}
91
120
  end
92
121
  end
data/lib/uglify.js CHANGED
@@ -48,8 +48,7 @@
48
48
  };
49
49
  }
50
50
  return this.require.define;
51
- }).call(this)({"parse-js": function(exports, require, module) {
52
- /***********************************************************************
51
+ }).call(this)({"parse-js": function(exports, require, module) {/***********************************************************************
53
52
 
54
53
  A JavaScript tokenizer / parser / beautifier / compressor.
55
54
 
@@ -240,7 +239,7 @@ var OPERATORS = array_to_hash([
240
239
  "||"
241
240
  ]);
242
241
 
243
- var WHITESPACE_CHARS = array_to_hash(characters(" \n\r\t\u200b"));
242
+ var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\v\u200b"));
244
243
 
245
244
  var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:"));
246
245
 
@@ -802,14 +801,17 @@ function parse($TEXT, exigent_mode, embed_tokens) {
802
801
  return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);
803
802
  };
804
803
 
805
- var statement = embed_tokens ? function() {
806
- var start = S.token;
807
- var ast = $statement.apply(this, arguments);
808
- ast[0] = add_tokens(ast[0], start, prev());
809
- return ast;
810
- } : $statement;
804
+ function maybe_embed_tokens(parser) {
805
+ if (embed_tokens) return function() {
806
+ var start = S.token;
807
+ var ast = parser.apply(this, arguments);
808
+ ast[0] = add_tokens(ast[0], start, prev());
809
+ return ast;
810
+ };
811
+ else return parser;
812
+ };
811
813
 
812
- function $statement() {
814
+ var statement = maybe_embed_tokens(function() {
813
815
  if (is("operator", "/")) {
814
816
  S.peeked = null;
815
817
  S.token = S.input(true); // force regexp
@@ -903,7 +905,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
903
905
  unexpected();
904
906
  }
905
907
  }
906
- };
908
+ });
907
909
 
908
910
  function labeled_statement(label) {
909
911
  S.labels.push(label);
@@ -919,7 +921,10 @@ function parse($TEXT, exigent_mode, embed_tokens) {
919
921
  };
920
922
 
921
923
  function break_cont(type) {
922
- var name = is("name") ? S.token.value : null;
924
+ var name;
925
+ if (!can_insert_semicolon()) {
926
+ name = is("name") ? S.token.value : null;
927
+ }
923
928
  if (name != null) {
924
929
  next();
925
930
  if (!member(name, S.labels))
@@ -961,14 +966,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
961
966
  return as("for-in", init, lhs, obj, in_loop(statement));
962
967
  };
963
968
 
964
- var function_ = embed_tokens ? function() {
965
- var start = prev();
966
- var ast = $function_.apply(this, arguments);
967
- ast[0] = add_tokens(ast[0], start, prev());
968
- return ast;
969
- } : $function_;
970
-
971
- function $function_(in_statement) {
969
+ var function_ = maybe_embed_tokens(function(in_statement) {
972
970
  var name = is("name") ? prog1(S.token.value, next) : null;
973
971
  if (in_statement && !name)
974
972
  unexpected();
@@ -996,7 +994,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
996
994
  S.in_loop = loop;
997
995
  return a;
998
996
  })());
999
- };
997
+ });
1000
998
 
1001
999
  function if_() {
1002
1000
  var cond = parenthesised(), body = statement(), belse;
@@ -1104,7 +1102,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
1104
1102
  return subscripts(as("new", newexp, args), true);
1105
1103
  };
1106
1104
 
1107
- function expr_atom(allow_calls) {
1105
+ var expr_atom = maybe_embed_tokens(function(allow_calls) {
1108
1106
  if (is("operator", "new")) {
1109
1107
  next();
1110
1108
  return new_();
@@ -1139,7 +1137,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
1139
1137
  return subscripts(prog1(atom, next), allow_calls);
1140
1138
  }
1141
1139
  unexpected();
1142
- };
1140
+ });
1143
1141
 
1144
1142
  function expr_list(closing, allow_trailing_comma, allow_empty) {
1145
1143
  var first = true, a = [];
@@ -1279,7 +1277,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
1279
1277
  return left;
1280
1278
  };
1281
1279
 
1282
- function expression(commas, no_in) {
1280
+ var expression = maybe_embed_tokens(function(commas, no_in) {
1283
1281
  if (arguments.length == 0)
1284
1282
  commas = true;
1285
1283
  var expr = maybe_assign(no_in);
@@ -1288,7 +1286,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
1288
1286
  return as("seq", expr, expression(true, no_in));
1289
1287
  }
1290
1288
  return expr;
1291
- };
1289
+ });
1292
1290
 
1293
1291
  function in_loop(cont) {
1294
1292
  try {
@@ -1445,6 +1443,12 @@ function ast_walker(ast) {
1445
1443
  return a;
1446
1444
  }) ];
1447
1445
  };
1446
+ function _block(statements) {
1447
+ var out = [ this[0] ];
1448
+ if (statements != null)
1449
+ out.push(MAP(statements, walk));
1450
+ return out;
1451
+ };
1448
1452
  var walkers = {
1449
1453
  "string": function(str) {
1450
1454
  return [ this[0], str ];
@@ -1458,12 +1462,8 @@ function ast_walker(ast) {
1458
1462
  "toplevel": function(statements) {
1459
1463
  return [ this[0], MAP(statements, walk) ];
1460
1464
  },
1461
- "block": function(statements) {
1462
- var out = [ this[0] ];
1463
- if (statements != null)
1464
- out.push(MAP(statements, walk));
1465
- return out;
1466
- },
1465
+ "block": _block,
1466
+ "splice": _block,
1467
1467
  "var": _vardefs,
1468
1468
  "const": _vardefs,
1469
1469
  "try": function(t, c, f) {
@@ -1747,7 +1747,9 @@ function ast_add_scope(ast) {
1747
1747
  };
1748
1748
 
1749
1749
  function _lambda(name, args, body) {
1750
- return [ this[0], define(name), args, with_new_scope(function(){
1750
+ var is_defun = this[0] == "defun";
1751
+ return [ this[0], is_defun ? define(name) : name, args, with_new_scope(function(){
1752
+ if (!is_defun) define(name);
1751
1753
  MAP(args, define);
1752
1754
  return MAP(body, walk);
1753
1755
  })];
@@ -1833,9 +1835,24 @@ function ast_mangle(ast, options) {
1833
1835
  return scope.get_mangled(name, newMangle);
1834
1836
  };
1835
1837
 
1838
+ function get_define(name) {
1839
+ if (options.defines) {
1840
+ // we always lookup a defined symbol for the current scope FIRST, so declared
1841
+ // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value
1842
+ if (!scope.has(name)) {
1843
+ if (HOP(options.defines, name)) {
1844
+ return options.defines[name];
1845
+ }
1846
+ }
1847
+ return null;
1848
+ }
1849
+ };
1850
+
1836
1851
  function _lambda(name, args, body) {
1837
- if (name) name = get_mangled(name);
1852
+ var is_defun = this[0] == "defun";
1853
+ if (is_defun && name) name = get_mangled(name);
1838
1854
  body = with_scope(body.scope, function(){
1855
+ if (!is_defun && name) name = get_mangled(name);
1839
1856
  args = MAP(args, function(name){ return get_mangled(name) });
1840
1857
  return MAP(body, walk);
1841
1858
  });
@@ -1877,7 +1894,7 @@ function ast_mangle(ast, options) {
1877
1894
  "var": _vardefs,
1878
1895
  "const": _vardefs,
1879
1896
  "name": function(name) {
1880
- return [ this[0], get_mangled(name) ];
1897
+ return get_define(name) || [ this[0], get_mangled(name) ];
1881
1898
  },
1882
1899
  "try": function(t, c, f) {
1883
1900
  return [ this[0],
@@ -1953,11 +1970,18 @@ function boolean_expr(expr) {
1953
1970
  };
1954
1971
 
1955
1972
  function make_conditional(c, t, e) {
1973
+ var make_real_conditional = function() {
1956
1974
  if (c[0] == "unary-prefix" && c[1] == "!") {
1957
- return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
1975
+ return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
1958
1976
  } else {
1959
- return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ];
1977
+ return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ];
1960
1978
  }
1979
+ };
1980
+ // shortcut the conditional if the expression has a constant value
1981
+ return when_constant(c, function(ast, val){
1982
+ warn_unreachable(val ? e : t);
1983
+ return (val ? t : e);
1984
+ }, make_real_conditional);
1961
1985
  };
1962
1986
 
1963
1987
  function empty(b) {
@@ -2046,6 +2070,18 @@ var when_constant = (function(){
2046
2070
  || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {
2047
2071
  expr[1] = expr[1].substr(0, 2);
2048
2072
  }
2073
+ else if (no && expr[0] == "binary"
2074
+ && (expr[1] == "||" || expr[1] == "&&")) {
2075
+ // the whole expression is not constant but the lval may be...
2076
+ try {
2077
+ var lval = evaluate(expr[2]);
2078
+ expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) ||
2079
+ (expr[1] == "||" && (lval ? lval : expr[3])) ||
2080
+ expr);
2081
+ } catch(ex2) {
2082
+ // IGNORE... lval is not constant
2083
+ }
2084
+ }
2049
2085
  return no ? no.call(expr, expr) : null;
2050
2086
  }
2051
2087
  else throw ex;
@@ -2121,9 +2157,14 @@ function ast_squeeze(ast, options) {
2121
2157
  };
2122
2158
 
2123
2159
  function _lambda(name, args, body) {
2124
- return [ this[0], name, args, with_scope(body.scope, function(){
2125
- return tighten(MAP(body, walk), "lambda");
2126
- }) ];
2160
+ var is_defun = this[0] == "defun";
2161
+ body = with_scope(body.scope, function(){
2162
+ var ret = tighten(MAP(body, walk), "lambda");
2163
+ if (!is_defun && name && !HOP(scope.refs, name))
2164
+ name = null;
2165
+ return ret;
2166
+ });
2167
+ return [ this[0], name, args, body ];
2127
2168
  };
2128
2169
 
2129
2170
  // we get here for blocks that have been already transformed.
@@ -2329,13 +2370,7 @@ function ast_squeeze(ast, options) {
2329
2370
  return [ branch[0] ? walk(branch[0]) : null, block ];
2330
2371
  }) ];
2331
2372
  },
2332
- "function": function() {
2333
- var ret = _lambda.apply(this, arguments);
2334
- if (ret[1] && !HOP(scope.refs, ret[1])) {
2335
- ret[1] = null;
2336
- }
2337
- return ret;
2338
- },
2373
+ "function": _lambda,
2339
2374
  "defun": _lambda,
2340
2375
  "block": function(body) {
2341
2376
  if (body) return rmblock([ "block", tighten(MAP(body, walk)) ]);
@@ -2387,8 +2422,7 @@ function ast_squeeze(ast, options) {
2387
2422
  return [ "array", args ];
2388
2423
  }
2389
2424
  },
2390
- "while": _do_while,
2391
- "do": _do_while
2425
+ "while": _do_while
2392
2426
  }, function() {
2393
2427
  return walk(ast_add_scope(ast));
2394
2428
  });
@@ -2409,7 +2443,7 @@ var DOT_CALL_NO_PARENS = jsp.array_to_hash([
2409
2443
 
2410
2444
  function make_string(str, ascii_only) {
2411
2445
  var dq = 0, sq = 0;
2412
- str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029]/g, function(s){
2446
+ str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){
2413
2447
  switch (s) {
2414
2448
  case "\\": return "\\\\";
2415
2449
  case "\b": return "\\b";
@@ -2421,6 +2455,7 @@ function make_string(str, ascii_only) {
2421
2455
  case "\u2029": return "\\u2029";
2422
2456
  case '"': ++dq; return '"';
2423
2457
  case "'": ++sq; return "'";
2458
+ case "\0": return "\\0";
2424
2459
  }
2425
2460
  return s;
2426
2461
  });
@@ -2437,6 +2472,8 @@ function to_ascii(str) {
2437
2472
  });
2438
2473
  };
2439
2474
 
2475
+ var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]);
2476
+
2440
2477
  function gen_code(ast, options) {
2441
2478
  options = defaults(options, {
2442
2479
  indent_start : 0,
@@ -2567,6 +2604,19 @@ function gen_code(ast, options) {
2567
2604
  return make_block_statements(statements)
2568
2605
  .join(newline + newline);
2569
2606
  },
2607
+ "splice": function(statements) {
2608
+ var parent = $stack[$stack.length - 2][0];
2609
+ if (HOP(SPLICE_NEEDS_BRACKETS, parent)) {
2610
+ // we need block brackets in this case
2611
+ return make_block.apply(this, arguments);
2612
+ } else {
2613
+ return MAP(make_block_statements(statements, true),
2614
+ function(line, i) {
2615
+ // the first line is already indented
2616
+ return i > 0 ? indent(line) : line;
2617
+ }).join(newline);
2618
+ }
2619
+ },
2570
2620
  "block": make_block,
2571
2621
  "var": function(defs) {
2572
2622
  return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
@@ -2807,7 +2857,7 @@ function gen_code(ast, options) {
2807
2857
  return add_spaces([ out, make_block(body) ]);
2808
2858
  };
2809
2859
 
2810
- function make_block_statements(statements) {
2860
+ function make_block_statements(statements, noindent) {
2811
2861
  for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {
2812
2862
  var stat = statements[i];
2813
2863
  var code = make(stat);
@@ -2825,7 +2875,7 @@ function gen_code(ast, options) {
2825
2875
  a.push(code);
2826
2876
  }
2827
2877
  }
2828
- return MAP(a, indent);
2878
+ return noindent ? a : MAP(a, indent);
2829
2879
  };
2830
2880
 
2831
2881
  function make_switch_block(body) {
@@ -2856,7 +2906,7 @@ function gen_code(ast, options) {
2856
2906
  function make_1vardef(def) {
2857
2907
  var name = def[0], val = def[1];
2858
2908
  if (val != null)
2859
- name = add_spaces([ make_name(name), "=", make(val) ]);
2909
+ name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]);
2860
2910
  return name;
2861
2911
  };
2862
2912
 
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require 'uglifier'
2
3
  require 'rspec'
3
4
 
@@ -1,8 +1,9 @@
1
+ # encoding: UTF-8
1
2
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
3
 
3
4
  describe "Uglifier" do
4
5
  it "minifies JS" do
5
- source = File.read("vendor/uglifyjs/lib/process.js")
6
+ source = File.open("vendor/uglifyjs/lib/process.js", "r:UTF-8").read
6
7
  minified = Uglifier.new.compile(source)
7
8
  minified.length.should < source.length
8
9
  lambda {
@@ -16,6 +17,10 @@ describe "Uglifier" do
16
17
  }.should raise_error(Uglifier::Error)
17
18
  end
18
19
 
20
+ it "doesn't omit null character in strings" do
21
+ Uglifier.new.compile('var foo="\0bar"').should match(/(\0|\\0)/)
22
+ end
23
+
19
24
  describe "Copyright Preservation" do
20
25
  before :all do
21
26
  @source = <<-EOS
@@ -63,16 +68,31 @@ describe "Uglifier" do
63
68
  Uglifier.compile(code, :squeeze => false).length.should > Uglifier.compile(code, :squeeze => true).length
64
69
  end
65
70
 
71
+ it "should allow top level variables to be mangled" do
72
+ code = "var foo = 123"
73
+ Uglifier.compile(code, :toplevel => true).should_not include("var foo")
74
+ end
75
+
76
+ it "allows variables to be excluded from mangling" do
77
+ code = "var foo = {bar: 123};"
78
+ Uglifier.compile(code, :except => ["foo"], :toplevel => true).should include("var foo")
79
+ end
80
+
81
+ it "honors max line length" do
82
+ code = "var foo = 123;var bar = 123456"
83
+ Uglifier.compile(code, :max_line_length => 8).split("\n").length.should == 2
84
+ end
85
+
66
86
  describe "Input Formats" do
67
87
  it "handles strings" do
68
88
  lambda {
69
- Uglifier.new.compile(File.read("vendor/uglifyjs/lib/process.js")).should_not be_empty
89
+ Uglifier.new.compile(File.open("vendor/uglifyjs/lib/process.js", "r:UTF-8").read).should_not be_empty
70
90
  }.should_not raise_error
71
91
  end
72
92
 
73
93
  it "handles files" do
74
94
  lambda {
75
- Uglifier.new.compile(File.open("vendor/uglifyjs/lib/process.js", "r")).should_not be_empty
95
+ Uglifier.new.compile(File.open("vendor/uglifyjs/lib/process.js", "r:UTF-8")).should_not be_empty
76
96
  }.should_not raise_error
77
97
  end
78
98
  end
data/uglifier.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{uglifier}
8
- s.version = "0.5.4"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = [%q{Ville Lautanala}]
12
- s.date = %q{2011-05-19}
12
+ s.date = %q{2011-06-21}
13
13
  s.email = %q{lautis@gmail.com}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE.txt",
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  ".document",
20
20
  ".gitmodules",
21
21
  ".rspec",
22
+ ".travis.yml",
22
23
  "Gemfile",
23
24
  "LICENSE.txt",
24
25
  "README.rdoc",
@@ -34,12 +35,8 @@ Gem::Specification.new do |s|
34
35
  ]
35
36
  s.homepage = %q{http://github.com/lautis/uglifier}
36
37
  s.require_paths = [%q{lib}]
37
- s.rubygems_version = %q{1.8.2}
38
+ s.rubygems_version = %q{1.8.4}
38
39
  s.summary = %q{Ruby wrapper for UglifyJS JavaScript compressor}
39
- s.test_files = [
40
- "spec/spec_helper.rb",
41
- "spec/uglifier_spec.rb"
42
- ]
43
40
 
44
41
  if s.respond_to? :specification_version then
45
42
  s.specification_version = 3
@@ -47,24 +44,24 @@ Gem::Specification.new do |s|
47
44
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
45
  s.add_runtime_dependency(%q<execjs>, [">= 0.3.0"])
49
46
  s.add_runtime_dependency(%q<multi_json>, [">= 1.0.2"])
50
- s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
47
+ s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
51
48
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
52
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.0"])
49
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
53
50
  s.add_development_dependency(%q<rcov>, [">= 0"])
54
51
  else
55
52
  s.add_dependency(%q<execjs>, [">= 0.3.0"])
56
53
  s.add_dependency(%q<multi_json>, [">= 1.0.2"])
57
- s.add_dependency(%q<rspec>, ["~> 2.5.0"])
54
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
58
55
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
59
- s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
56
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
60
57
  s.add_dependency(%q<rcov>, [">= 0"])
61
58
  end
62
59
  else
63
60
  s.add_dependency(%q<execjs>, [">= 0.3.0"])
64
61
  s.add_dependency(%q<multi_json>, [">= 1.0.2"])
65
- s.add_dependency(%q<rspec>, ["~> 2.5.0"])
62
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
66
63
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
67
- s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
64
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
68
65
  s.add_dependency(%q<rcov>, [">= 0"])
69
66
  end
70
67
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uglifier
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 5
9
- - 4
10
- version: 0.5.4
9
+ - 0
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ville Lautanala
@@ -15,10 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-19 00:00:00 Z
18
+ date: 2011-06-21 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- version_requirements: &id001 !ruby/object:Gem::Requirement
21
+ type: :runtime
22
+ requirement: &id001 !ruby/object:Gem::Requirement
22
23
  none: false
23
24
  requirements:
24
25
  - - ">="
@@ -29,12 +30,12 @@ dependencies:
29
30
  - 3
30
31
  - 0
31
32
  version: 0.3.0
32
- type: :runtime
33
- requirement: *id001
34
33
  prerelease: false
34
+ version_requirements: *id001
35
35
  name: execjs
36
36
  - !ruby/object:Gem::Dependency
37
- version_requirements: &id002 !ruby/object:Gem::Requirement
37
+ type: :runtime
38
+ requirement: &id002 !ruby/object:Gem::Requirement
38
39
  none: false
39
40
  requirements:
40
41
  - - ">="
@@ -45,28 +46,28 @@ dependencies:
45
46
  - 0
46
47
  - 2
47
48
  version: 1.0.2
48
- type: :runtime
49
- requirement: *id002
50
49
  prerelease: false
50
+ version_requirements: *id002
51
51
  name: multi_json
52
52
  - !ruby/object:Gem::Dependency
53
- version_requirements: &id003 !ruby/object:Gem::Requirement
53
+ type: :development
54
+ requirement: &id003 !ruby/object:Gem::Requirement
54
55
  none: false
55
56
  requirements:
56
57
  - - ~>
57
58
  - !ruby/object:Gem::Version
58
- hash: 27
59
+ hash: 23
59
60
  segments:
60
61
  - 2
61
- - 5
62
+ - 6
62
63
  - 0
63
- version: 2.5.0
64
- type: :development
65
- requirement: *id003
64
+ version: 2.6.0
66
65
  prerelease: false
66
+ version_requirements: *id003
67
67
  name: rspec
68
68
  - !ruby/object:Gem::Dependency
69
- version_requirements: &id004 !ruby/object:Gem::Requirement
69
+ type: :development
70
+ requirement: &id004 !ruby/object:Gem::Requirement
70
71
  none: false
71
72
  requirements:
72
73
  - - ~>
@@ -77,28 +78,28 @@ dependencies:
77
78
  - 0
78
79
  - 0
79
80
  version: 1.0.0
80
- type: :development
81
- requirement: *id004
82
81
  prerelease: false
82
+ version_requirements: *id004
83
83
  name: bundler
84
84
  - !ruby/object:Gem::Dependency
85
- version_requirements: &id005 !ruby/object:Gem::Requirement
85
+ type: :development
86
+ requirement: &id005 !ruby/object:Gem::Requirement
86
87
  none: false
87
88
  requirements:
88
89
  - - ~>
89
90
  - !ruby/object:Gem::Version
90
- hash: 3
91
+ hash: 15
91
92
  segments:
92
93
  - 1
93
- - 5
94
+ - 6
94
95
  - 0
95
- version: 1.5.0
96
- type: :development
97
- requirement: *id005
96
+ version: 1.6.0
98
97
  prerelease: false
98
+ version_requirements: *id005
99
99
  name: jeweler
100
100
  - !ruby/object:Gem::Dependency
101
- version_requirements: &id006 !ruby/object:Gem::Requirement
101
+ type: :development
102
+ requirement: &id006 !ruby/object:Gem::Requirement
102
103
  none: false
103
104
  requirements:
104
105
  - - ">="
@@ -107,9 +108,8 @@ dependencies:
107
108
  segments:
108
109
  - 0
109
110
  version: "0"
110
- type: :development
111
- requirement: *id006
112
111
  prerelease: false
112
+ version_requirements: *id006
113
113
  name: rcov
114
114
  description:
115
115
  email: lautis@gmail.com
@@ -124,6 +124,7 @@ files:
124
124
  - .document
125
125
  - .gitmodules
126
126
  - .rspec
127
+ - .travis.yml
127
128
  - Gemfile
128
129
  - LICENSE.txt
129
130
  - README.rdoc
@@ -165,10 +166,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
166
  requirements: []
166
167
 
167
168
  rubyforge_project:
168
- rubygems_version: 1.8.2
169
+ rubygems_version: 1.8.4
169
170
  signing_key:
170
171
  specification_version: 3
171
172
  summary: Ruby wrapper for UglifyJS JavaScript compressor
172
- test_files:
173
- - spec/spec_helper.rb
174
- - spec/uglifier_spec.rb
173
+ test_files: []
174
+