uglifier 0.2.0 → 0.3.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/Gemfile CHANGED
@@ -3,13 +3,13 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
- gem "therubyracer", ">= 0.7.5"
6
+ gem "therubyracer", ">= 0.8.0"
7
7
 
8
8
  # Add dependencies to develop your gem here.
9
9
  # Include everything needed to run rake, tests, features, etc.
10
10
  group :development do
11
- gem "rspec", "~> 2.0.0"
11
+ gem "rspec", "~> 2.3.0"
12
12
  gem "bundler", "~> 1.0.0"
13
- gem "jeweler", "~> 1.5.0.pre5"
13
+ gem "jeweler", "~> 1.5.0"
14
14
  gem "rcov", ">= 0"
15
15
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
data/bin/uglify ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+ require 'uglifier'
4
+ require 'uglifier/cli'
5
+
6
+ exit Uglifier::Cli.run!
data/lib/uglifier.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "v8"
1
+ require "uglifier/node"
2
2
 
3
3
  class Uglifier
4
4
  # Raised when compilation fails
@@ -12,6 +12,7 @@ class Uglifier
12
12
  :dead_code => true, # Remove dead code (e.g. after return)
13
13
  :extra => false, # Additional and potentially unsafe optimizations
14
14
  :unsafe => false, # Optimizations known to be unsafe in some situations
15
+ :copyright => true, # Show copyright message
15
16
  :beautify => false, # Ouput indented code
16
17
  :beautify_options => {
17
18
  :indent_level => 4,
@@ -21,27 +22,26 @@ class Uglifier
21
22
  }
22
23
  }
23
24
 
25
+ # Create new instance of Uglifier with given options
24
26
  def initialize(options = {})
25
27
  @options = DEFAULTS.merge(options)
26
- @exports = {
27
- "sys" => {
28
- :debug => lambda {|m| puts m }
29
- }
30
- }
28
+ @node = Node.new do |cxt|
29
+ @tokenizer = cxt.require("parse-js")["tokenizer"]
30
+ process = cxt.require("process")
31
+ process["set_logger"].call(lambda {|m| $stderr.puts m })
32
+ end
31
33
  end
32
34
 
33
35
  def compile(source)
34
- V8::Context.new do |cxt|
35
- cxt["process"] = { :version => "v0.2.0" }
36
-
37
- load_file(cxt, "parse-js")
38
- load_file(cxt, "process")
39
- begin
40
- return generate_code(cxt, ast(cxt, source))
41
- rescue Exception => e
42
- raise Error.new(e.message)
43
- end
44
- end
36
+ str = stringify(source)
37
+
38
+ if @options[:copyright]
39
+ copyright(str)
40
+ else
41
+ ""
42
+ end << generate_code(ast(str))
43
+ rescue V8::JSError => e
44
+ raise Error.new(e.message)
45
45
  end
46
46
 
47
47
  def self.compile(source, options = {})
@@ -50,46 +50,58 @@ class Uglifier
50
50
 
51
51
  private
52
52
 
53
- def generate_code(cxt, ast)
54
- cxt["gen_code"].call(ast, @options[:beautify] && @options[:beautify_options])
53
+ def stringify(source)
54
+ if source.respond_to? :read
55
+ source.read
56
+ else
57
+ source.to_s
58
+ end
55
59
  end
56
60
 
57
- def ast(cxt, source)
58
- squeeze_unsafe(cxt, squeeze(cxt, mangle(cxt, cxt["parse"].call(source))))
61
+ def copyright(source)
62
+ comments = []
63
+
64
+ tokens = @tokenizer.call(source, false)
65
+ comment = tokens.call
66
+ prev = nil
67
+
68
+ while (comment["type"].match(/^comment/) && (!prev || prev == comment["type"]))
69
+ comments << if comment["type"] == "comment1"
70
+ "//#{comment["value"]}\n"
71
+ else
72
+ "/*#{comment["value"]}*/\n"
73
+ end
74
+ prev = comment["type"]
75
+ comment = tokens.call
76
+ end
77
+ comments.join
59
78
  end
60
79
 
61
- def mangle(cxt, ast)
80
+ def generate_code(ast)
81
+ @node["gen_code"].call(ast, @options[:beautify] && @options[:beautify_options])
82
+ end
83
+
84
+ def ast(source)
85
+ squeeze_unsafe(squeeze(mangle(@node["parse"].call(source))))
86
+ end
87
+
88
+ def mangle(ast)
62
89
  return ast unless @options[:mangle]
63
- cxt["ast_mangle"].call(ast, @options[:toplevel])
90
+ @node["ast_mangle"].call(ast, @options[:toplevel])
64
91
  end
65
92
 
66
- def squeeze(cxt, ast)
93
+ def squeeze(ast)
67
94
  return ast unless @options[:squeeze]
68
95
 
69
- cxt["ast_squeeze"].call(ast, {
96
+ @node["ast_squeeze"].call(ast, {
70
97
  "make_seqs" => @options[:seqs],
71
98
  "dead_code" => @options[:dead_code],
72
99
  "extra" => @options[:extra]
73
100
  })
74
101
  end
75
102
 
76
- def squeeze_unsafe(cxt, ast)
103
+ def squeeze_unsafe(ast)
77
104
  return ast unless @options[:unsafe]
78
- cxt["ast_squeeze_more"].call(ast)
79
- end
80
-
81
- def load_file(cxt, file)
82
- old = cxt["exports"]
83
- cxt["exports"] = {}
84
- cxt["require"] = lambda {|r|
85
- @exports[File.basename(r, ".js")] || begin
86
- @exports[file] = cxt["exports"] # Prevent circular dependencies
87
- load_file(cxt, File.basename(r, ".js"))
88
- end
89
- }
90
- cxt.load(File.join(File.dirname(__FILE__), "..", "vendor", "uglifyjs", "lib", File.basename(file, ".js") + ".js"))
91
- @exports[file] = cxt["exports"]
92
- cxt["exports"] = old
93
- @exports[file]
105
+ @node["ast_squeeze_more"].call(ast)
94
106
  end
95
107
  end
@@ -0,0 +1,62 @@
1
+ require 'optparse'
2
+
3
+ class Uglifier
4
+ module Cli
5
+ def self.run!
6
+ options = {}
7
+ OptionParser.new do |opts|
8
+ opts.banner = "Usage: uglifier [options] file1 file2 ..."
9
+
10
+ opts.on("-M", "--no-mangle", "Don't mangle variable names") do |m|
11
+ options[:mangle] = m
12
+ end
13
+
14
+ opts.on("-t", "--toplevel", "Mangle top-level variable names") do |m|
15
+ options[:toplevel] = m
16
+ end
17
+
18
+ opts.on("-S", "--no-squeeze", "Squeeze code resulting in smaller, but less-readable code") do |s|
19
+ options[:squeeze] = s
20
+ end
21
+
22
+ opts.on("-Q", "--no-seqs", "Reduce consecutive statements in blocks into single statement") do |q|
23
+ options[:seqs] = q
24
+ end
25
+
26
+ opts.on("-d", "--[no-]dead-code", "Remove dead code (e.g. after return)") do |d|
27
+ options[:dead_code] = d
28
+ end
29
+
30
+ opts.on("-x", "--extra-optimizations", "Additional and potentially unsafe optimizations") do |x|
31
+ options[:extra] = x
32
+ end
33
+
34
+ opts.on("-u", "--unsafe-optimizations", "Optimizations known to be unsafe in some situations") do |d|
35
+ options[:unsafe] = d
36
+ end
37
+
38
+ opts.on("-C", "--no-copyright", "Omit copyright information") do |d|
39
+ options[:copyright] = d
40
+ end
41
+
42
+ opts.on("-b", "--beautify", "Output indented code") do |d|
43
+ options[:beautify] = d
44
+ end
45
+
46
+ opts.on("-v", "--verbose", "Run verbosely") do |v|
47
+ options[:verbose] = v
48
+ end
49
+ end.parse!
50
+
51
+ uglifier = Uglifier.new(options)
52
+ if ARGV[0]
53
+ ARGV.each do |f|
54
+ puts uglifier.compile(File.open(f, 'r'))
55
+ end
56
+ else
57
+ puts uglifier.compile($stdin)
58
+ end
59
+ true
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,24 @@
1
+ require "v8"
2
+
3
+ class Uglifier
4
+ class Node < V8::Context
5
+ def initialize(*args, &blk)
6
+ @exports = {}
7
+ super(*args, &blk)
8
+ end
9
+ def require(file)
10
+ old = self["exports"]
11
+ self["exports"] = {}
12
+ self["require"] = lambda {|r|
13
+ @exports[File.basename(r, ".js")] || begin
14
+ @exports[file] = self["exports"] # Prevent circular dependencies
15
+ self.require(File.basename(r, ".js"))
16
+ end
17
+ }
18
+ load(File.join(File.dirname(__FILE__), "..", "..", "vendor", "uglifyjs", "lib", File.basename(file, ".js") + ".js"))
19
+ @exports[file] = self["exports"]
20
+ self["exports"] = old
21
+ @exports[file]
22
+ end
23
+ end
24
+ end
@@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "Uglifier" do
4
4
  it "minifies JS" do
5
- source = File.read("vendor/uglifyjs/lib/parse-js.js")
5
+ source = File.read("vendor/uglifyjs/lib/process.js")
6
6
  minified = Uglifier.new.compile(source)
7
7
  minified.length.should < source.length
8
8
  lambda {
@@ -16,8 +16,8 @@ describe "Uglifier" do
16
16
  }.should raise_error(Uglifier::Error)
17
17
  end
18
18
 
19
- it "logs to output" do
20
- $stdout.should_receive(:write).at_least(:once)
19
+ it "logs to stderr" do
20
+ $stderr.should_receive(:write).at_least(:once)
21
21
  lambda {
22
22
  Uglifier.new.compile("function uglifyThis() {
23
23
  return;
@@ -26,6 +26,38 @@ describe "Uglifier" do
26
26
  }.should_not raise_error(Uglifier::Error)
27
27
  end
28
28
 
29
+ describe "Copyright Preservation" do
30
+ before :all do
31
+ @source = <<-EOS
32
+ /* Copyright Notice */
33
+ /* (c) 2011 */
34
+ // REMOVED
35
+ function identity(p) { return p; }
36
+ EOS
37
+ @minified = Uglifier.compile(@source, :copyright => true)
38
+ end
39
+
40
+ it "preserves copyright notice" do
41
+ @minified.should match /Copyright Notice/
42
+ end
43
+
44
+ it "handles multiple copyright blocks" do
45
+ @minified.should match /\(c\) 2011/
46
+ end
47
+
48
+ it "doesn't include different comment types" do
49
+ @minified.should_not match /REMOVED/
50
+ end
51
+
52
+ it "puts comments on own lines" do
53
+ @minified.split("\n").should have(3).items
54
+ end
55
+
56
+ it "omits copyright notification if copyright parameter is set to false" do
57
+ Uglifier.compile(@source, :copyright => false).should_not match /Copyright/
58
+ end
59
+ end
60
+
29
61
  it "does additional squeezing when unsafe options is true" do
30
62
  unsafe_input = "function a(b){b.toString();}"
31
63
  Uglifier.new(:unsafe => true).compile(unsafe_input).length.should < Uglifier.new(:unsafe => false).compile(unsafe_input).length
@@ -40,4 +72,18 @@ describe "Uglifier" do
40
72
  code = "function a(a){if(a) { return 0; } else { return 1; }}"
41
73
  Uglifier.compile(code, :squeeze => false).length.should > Uglifier.compile(code, :squeeze => true).length
42
74
  end
75
+
76
+ describe "Input Formats" do
77
+ it "handles strings" do
78
+ lambda {
79
+ Uglifier.new.compile(File.read("vendor/uglifyjs/lib/process.js")).should_not be_empty
80
+ }.should_not raise_error
81
+ end
82
+
83
+ it "handles files" do
84
+ lambda {
85
+ Uglifier.new.compile(File.open("vendor/uglifyjs/lib/process.js", "r")).should_not be_empty
86
+ }.should_not raise_error
87
+ end
88
+ end
43
89
  end
data/uglifier.gemspec CHANGED
@@ -1,16 +1,18 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{uglifier}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ville Lautanala"]
12
- s.date = %q{2010-11-24}
12
+ s.date = %q{2011-01-06}
13
+ s.default_executable = %q{uglify}
13
14
  s.email = %q{lautis@gmail.com}
15
+ s.executables = ["uglify"]
14
16
  s.extra_rdoc_files = [
15
17
  "LICENSE.txt",
16
18
  "README.rdoc"
@@ -24,7 +26,10 @@ Gem::Specification.new do |s|
24
26
  "README.rdoc",
25
27
  "Rakefile",
26
28
  "VERSION",
29
+ "bin/uglify",
27
30
  "lib/uglifier.rb",
31
+ "lib/uglifier/cli.rb",
32
+ "lib/uglifier/node.rb",
28
33
  "spec/spec_helper.rb",
29
34
  "spec/uglifier_spec.rb",
30
35
  "uglifier.gemspec",
@@ -46,10 +51,10 @@ Gem::Specification.new do |s|
46
51
  s.specification_version = 3
47
52
 
48
53
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
- s.add_runtime_dependency(%q<therubyracer>, [">= 0.7.5"])
50
- s.add_development_dependency(%q<rspec>, ["~> 2.0.0"])
54
+ s.add_runtime_dependency(%q<therubyracer>, [">= 0.8.0"])
55
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
51
56
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
52
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
57
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.0"])
53
58
  s.add_development_dependency(%q<rcov>, [">= 0"])
54
59
  s.add_development_dependency(%q<therubyracer>, [">= 0.7.5"])
55
60
  s.add_development_dependency(%q<rspec>, ["~> 2.0.0"])
@@ -57,10 +62,10 @@ Gem::Specification.new do |s|
57
62
  s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
58
63
  s.add_development_dependency(%q<rcov>, [">= 0"])
59
64
  else
60
- s.add_dependency(%q<therubyracer>, [">= 0.7.5"])
61
- s.add_dependency(%q<rspec>, ["~> 2.0.0"])
65
+ s.add_dependency(%q<therubyracer>, [">= 0.8.0"])
66
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
62
67
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
63
- s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
68
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
64
69
  s.add_dependency(%q<rcov>, [">= 0"])
65
70
  s.add_dependency(%q<therubyracer>, [">= 0.7.5"])
66
71
  s.add_dependency(%q<rspec>, ["~> 2.0.0"])
@@ -69,10 +74,10 @@ Gem::Specification.new do |s|
69
74
  s.add_dependency(%q<rcov>, [">= 0"])
70
75
  end
71
76
  else
72
- s.add_dependency(%q<therubyracer>, [">= 0.7.5"])
73
- s.add_dependency(%q<rspec>, ["~> 2.0.0"])
77
+ s.add_dependency(%q<therubyracer>, [">= 0.8.0"])
78
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
74
79
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
75
- s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
80
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
76
81
  s.add_dependency(%q<rcov>, [">= 0"])
77
82
  s.add_dependency(%q<therubyracer>, [">= 0.7.5"])
78
83
  s.add_dependency(%q<rspec>, ["~> 2.0.0"])
@@ -24,29 +24,36 @@
24
24
  <mihai.bazon@gmail.com>
25
25
  http://mihai.bazon.net/blog
26
26
 
27
- Distributed under the same terms as the original code (ZLIB license):
27
+ Distributed under the BSD license:
28
28
 
29
29
  Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
30
30
  Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
31
31
 
32
- This software is provided 'as-is', without any express or implied
33
- warranty. In no event will the authors be held liable for any
34
- damages arising from the use of this software.
35
-
36
- Permission is granted to anyone to use this software for any
37
- purpose, including commercial applications, and to alter it and
38
- redistribute it freely, subject to the following restrictions:
39
-
40
- 1. The origin of this software must not be misrepresented; you must
41
- not claim that you wrote the original software. If you use this
42
- software in a product, an acknowledgment in the product
43
- documentation would be appreciated but is not required.
44
-
45
- 2. Altered source versions must be plainly marked as such, and must
46
- not be misrepresented as being the original software.
47
-
48
- 3. This notice may not be removed or altered from any source
49
- distribution.
32
+ Redistribution and use in source and binary forms, with or without
33
+ modification, are permitted provided that the following conditions
34
+ are met:
35
+
36
+ * Redistributions of source code must retain the above
37
+ copyright notice, this list of conditions and the following
38
+ disclaimer.
39
+
40
+ * Redistributions in binary form must reproduce the above
41
+ copyright notice, this list of conditions and the following
42
+ disclaimer in the documentation and/or other materials
43
+ provided with the distribution.
44
+
45
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
46
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
49
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
50
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
54
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
55
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56
+ SUCH DAMAGE.
50
57
 
51
58
  ***********************************************************************/
52
59
 
@@ -118,7 +125,8 @@ var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([
118
125
  "new",
119
126
  "delete",
120
127
  "throw",
121
- "else"
128
+ "else",
129
+ "case"
122
130
  ]);
123
131
 
124
132
  var KEYWORDS_ATOM = array_to_hash([
@@ -414,6 +422,7 @@ function tokenizer($TEXT, skip_comments) {
414
422
  text = S.text.substring(S.pos, i),
415
423
  tok = token("comment2", text);
416
424
  S.pos = i + 2;
425
+ S.line += text.split("\n").length - 1;
417
426
  S.newline_before = text.indexOf("\n") >= 0;
418
427
  return tok;
419
428
  });
@@ -1031,10 +1040,14 @@ function parse($TEXT, strict_mode, embed_tokens) {
1031
1040
  if (!strict_mode && is("punc", "}"))
1032
1041
  // allow trailing comma
1033
1042
  break;
1043
+ var type = S.token.type;
1034
1044
  var name = as_property_name();
1035
- expect(":");
1036
- var value = expression(false);
1037
- a.push([ name, value ]);
1045
+ if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) {
1046
+ a.push([ as_name(), function_(false), name ]);
1047
+ } else {
1048
+ expect(":");
1049
+ a.push([ name, expression(false) ]);
1050
+ }
1038
1051
  }
1039
1052
  next();
1040
1053
  return as("object", a);
@@ -27,28 +27,35 @@
27
27
  <mihai.bazon@gmail.com>
28
28
  http://mihai.bazon.net/blog
29
29
 
30
- Distributed under a ZLIB license:
30
+ Distributed under the BSD license:
31
31
 
32
32
  Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
33
33
 
34
- This software is provided 'as-is', without any express or implied
35
- warranty. In no event will the authors be held liable for any
36
- damages arising from the use of this software.
37
-
38
- Permission is granted to anyone to use this software for any
39
- purpose, including commercial applications, and to alter it and
40
- redistribute it freely, subject to the following restrictions:
41
-
42
- 1. The origin of this software must not be misrepresented; you must
43
- not claim that you wrote the original software. If you use this
44
- software in a product, an acknowledgment in the product
45
- documentation would be appreciated but is not required.
46
-
47
- 2. Altered source versions must be plainly marked as such, and must
48
- not be misrepresented as being the original software.
49
-
50
- 3. This notice may not be removed or altered from any source
51
- distribution.
34
+ Redistribution and use in source and binary forms, with or without
35
+ modification, are permitted provided that the following conditions
36
+ are met:
37
+
38
+ * Redistributions of source code must retain the above
39
+ copyright notice, this list of conditions and the following
40
+ disclaimer.
41
+
42
+ * Redistributions in binary form must reproduce the above
43
+ copyright notice, this list of conditions and the following
44
+ disclaimer in the documentation and/or other materials
45
+ provided with the distribution.
46
+
47
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
48
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
51
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
52
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
53
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
54
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
56
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
57
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58
+ SUCH DAMAGE.
52
59
 
53
60
  ***********************************************************************/
54
61
 
@@ -58,13 +65,11 @@ var jsp = require("./parse-js"),
58
65
  PRECEDENCE = jsp.PRECEDENCE,
59
66
  OPERATORS = jsp.OPERATORS;
60
67
 
61
- var sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util");
62
-
63
68
  /* -----[ helper for AST traversal ]----- */
64
69
 
65
70
  function ast_walker(ast) {
66
71
  function _vardefs(defs) {
67
- return defs.map(function(def){
72
+ return MAP(defs, function(def){
68
73
  var a = [ def[0] ];
69
74
  if (def.length > 1)
70
75
  a[1] = walk(def[1]);
@@ -82,12 +87,12 @@ function ast_walker(ast) {
82
87
  return [ "name", name ];
83
88
  },
84
89
  "toplevel": function(statements) {
85
- return [ "toplevel", statements.map(walk) ];
90
+ return [ "toplevel", MAP(statements, walk) ];
86
91
  },
87
92
  "block": function(statements) {
88
93
  var out = [ "block" ];
89
94
  if (statements != null)
90
- out.push(statements.map(walk));
95
+ out.push(MAP(statements, walk));
91
96
  return out;
92
97
  },
93
98
  "var": function(defs) {
@@ -99,21 +104,21 @@ function ast_walker(ast) {
99
104
  "try": function(t, c, f) {
100
105
  return [
101
106
  "try",
102
- t.map(walk),
103
- c != null ? [ c[0], c[1].map(walk) ] : null,
104
- f != null ? f.map(walk) : null
107
+ MAP(t, walk),
108
+ c != null ? [ c[0], MAP(c[1], walk) ] : null,
109
+ f != null ? MAP(f, walk) : null
105
110
  ];
106
111
  },
107
112
  "throw": function(expr) {
108
113
  return [ "throw", walk(expr) ];
109
114
  },
110
115
  "new": function(ctor, args) {
111
- return [ "new", walk(ctor), args.map(walk) ];
116
+ return [ "new", walk(ctor), MAP(args, walk) ];
112
117
  },
113
118
  "switch": function(expr, body) {
114
- return [ "switch", walk(expr), body.map(function(branch){
119
+ return [ "switch", walk(expr), MAP(body, function(branch){
115
120
  return [ branch[0] ? walk(branch[0]) : null,
116
- branch[1].map(walk) ];
121
+ MAP(branch[1], walk) ];
117
122
  }) ];
118
123
  },
119
124
  "break": function(label) {
@@ -132,13 +137,13 @@ function ast_walker(ast) {
132
137
  return [ "dot", walk(expr) ].concat(slice(arguments, 1));
133
138
  },
134
139
  "call": function(expr, args) {
135
- return [ "call", walk(expr), args.map(walk) ];
140
+ return [ "call", walk(expr), MAP(args, walk) ];
136
141
  },
137
142
  "function": function(name, args, body) {
138
- return [ "function", name, args.slice(), body.map(walk) ];
143
+ return [ "function", name, args.slice(), MAP(body, walk) ];
139
144
  },
140
145
  "defun": function(name, args, body) {
141
- return [ "defun", name, args.slice(), body.map(walk) ];
146
+ return [ "defun", name, args.slice(), MAP(body, walk) ];
142
147
  },
143
148
  "if": function(conditional, t, e) {
144
149
  return [ "if", walk(conditional), walk(t), walk(e) ];
@@ -171,21 +176,23 @@ function ast_walker(ast) {
171
176
  return [ "sub", walk(expr), walk(subscript) ];
172
177
  },
173
178
  "object": function(props) {
174
- return [ "object", props.map(function(p){
175
- return [ p[0], walk(p[1]) ];
179
+ return [ "object", MAP(props, function(p){
180
+ return p.length == 2
181
+ ? [ p[0], walk(p[1]) ]
182
+ : [ p[0], walk(p[1]), p[2] ]; // get/set-ter
176
183
  }) ];
177
184
  },
178
185
  "regexp": function(rx, mods) {
179
186
  return [ "regexp", rx, mods ];
180
187
  },
181
188
  "array": function(elements) {
182
- return [ "array", elements.map(walk) ];
189
+ return [ "array", MAP(elements, walk) ];
183
190
  },
184
191
  "stat": function(stat) {
185
192
  return [ "stat", walk(stat) ];
186
193
  },
187
194
  "seq": function() {
188
- return [ "seq" ].concat(slice(arguments).map(walk));
195
+ return [ "seq" ].concat(MAP(slice(arguments), walk));
189
196
  },
190
197
  "label": function(name, block) {
191
198
  return [ "label", name, walk(block) ];
@@ -225,13 +232,12 @@ function ast_walker(ast) {
225
232
  save[i] = user[i];
226
233
  user[i] = walkers[i];
227
234
  }
228
- try { return cont(); }
229
- finally {
230
- for (i in save) if (HOP(save, i)) {
231
- if (!save[i]) delete user[i];
232
- else user[i] = save[i];
233
- }
235
+ var ret = cont();
236
+ for (i in save) if (HOP(save, i)) {
237
+ if (!save[i]) delete user[i];
238
+ else user[i] = save[i];
234
239
  }
240
+ return ret;
235
241
  };
236
242
 
237
243
  return {
@@ -377,8 +383,8 @@ function ast_add_scope(ast) {
377
383
 
378
384
  function _lambda(name, args, body) {
379
385
  return [ this[0], define(name), args, with_new_scope(function(){
380
- args.map(define);
381
- return body.map(walk);
386
+ MAP(args, define);
387
+ return MAP(body, walk);
382
388
  })];
383
389
  };
384
390
 
@@ -392,17 +398,17 @@ function ast_add_scope(ast) {
392
398
  s.uses_with = true;
393
399
  },
394
400
  "var": function(defs) {
395
- defs.map(function(d){ define(d[0]) });
401
+ MAP(defs, function(d){ define(d[0]) });
396
402
  },
397
403
  "const": function(defs) {
398
- defs.map(function(d){ define(d[0]) });
404
+ MAP(defs, function(d){ define(d[0]) });
399
405
  },
400
406
  "try": function(t, c, f) {
401
407
  if (c != null) return [
402
408
  "try",
403
- t.map(walk),
404
- [ define(c[0]), c[1].map(walk) ],
405
- f != null ? f.map(walk) : null
409
+ MAP(t, walk),
410
+ [ define(c[0]), MAP(c[1], walk) ],
411
+ f != null ? MAP(f, walk) : null
406
412
  ];
407
413
  },
408
414
  "name": function(name) {
@@ -424,7 +430,7 @@ function ast_add_scope(ast) {
424
430
  // scopes where eval was detected and their parents
425
431
  // are marked with uses_eval, unless they define the
426
432
  // "eval" name.
427
- having_eval.map(function(scope){
433
+ MAP(having_eval, function(scope){
428
434
  if (!scope.has("eval")) while (scope) {
429
435
  scope.uses_eval = true;
430
436
  scope = scope.parent;
@@ -466,8 +472,8 @@ function ast_mangle(ast, do_toplevel) {
466
472
  function _lambda(name, args, body) {
467
473
  if (name) name = get_mangled(name);
468
474
  body = with_scope(body.scope, function(){
469
- args = args.map(function(name){ return get_mangled(name) });
470
- return body.map(walk);
475
+ args = MAP(args, function(name){ return get_mangled(name) });
476
+ return MAP(body, walk);
471
477
  });
472
478
  return [ this[0], name, args, body ];
473
479
  };
@@ -478,19 +484,32 @@ function ast_mangle(ast, do_toplevel) {
478
484
  for (var i in s.names) if (HOP(s.names, i)) {
479
485
  get_mangled(i, true);
480
486
  }
481
- try { var ret = cont(); ret.scope = s; return ret; }
482
- finally { scope = _scope; };
487
+ var ret = cont();
488
+ ret.scope = s;
489
+ scope = _scope;
490
+ return ret;
483
491
  };
484
492
 
485
493
  function _vardefs(defs) {
486
- return defs.map(function(d){
494
+ return MAP(defs, function(d){
487
495
  return [ get_mangled(d[0]), walk(d[1]) ];
488
496
  });
489
497
  };
490
498
 
491
499
  return w.with_walkers({
492
500
  "function": _lambda,
493
- "defun": _lambda,
501
+ "defun": function() {
502
+ // move function declarations to the top when
503
+ // they are not in some block.
504
+ var ast = _lambda.apply(this, arguments);
505
+ switch (w.parent()[0]) {
506
+ case "toplevel":
507
+ case "function":
508
+ case "defun":
509
+ return MAP.at_top(ast);
510
+ }
511
+ return ast;
512
+ },
494
513
  "var": function(defs) {
495
514
  return [ "var", _vardefs(defs) ];
496
515
  },
@@ -502,13 +521,13 @@ function ast_mangle(ast, do_toplevel) {
502
521
  },
503
522
  "try": function(t, c, f) {
504
523
  return [ "try",
505
- t.map(walk),
506
- c != null ? [ get_mangled(c[0]), c[1].map(walk) ] : null,
507
- f != null ? f.map(walk) : null ];
524
+ MAP(t, walk),
525
+ c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null,
526
+ f != null ? MAP(f, walk) : null ];
508
527
  },
509
528
  "toplevel": function(body) {
510
529
  return with_scope(this.scope, function(){
511
- return [ "toplevel", body.map(walk) ];
530
+ return [ "toplevel", MAP(body, walk) ];
512
531
  });
513
532
  },
514
533
  "for-in": function(has_var, name, obj, stat) {
@@ -530,9 +549,7 @@ function ast_mangle(ast, do_toplevel) {
530
549
  - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}
531
550
  ]----- */
532
551
 
533
- function warn(msg) {
534
- sys.debug(msg);
535
- };
552
+ var warn = function(){};
536
553
 
537
554
  function best_of(ast1, ast2) {
538
555
  return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1;
@@ -556,13 +573,7 @@ function negate(c) {
556
573
  var not_c = [ "unary-prefix", "!", c ];
557
574
  switch (c[0]) {
558
575
  case "unary-prefix":
559
- return c[1] == "!" ? c[2] : c;
560
- case "atom":
561
- switch (c[1]) {
562
- case "false": return [ "num", 0 ];
563
- case "true": return [ "num", 1 ];
564
- }
565
- break;
576
+ return c[1] == "!" ? c[2] : not_c;
566
577
  case "binary":
567
578
  var op = c[1], left = c[2], right = c[3];
568
579
  switch (op) {
@@ -602,7 +613,16 @@ function ast_squeeze(ast, options) {
602
613
  extra : false
603
614
  });
604
615
 
605
- var w = ast_walker(), walk = w.walk;
616
+ var w = ast_walker(), walk = w.walk, scope;
617
+
618
+ function with_scope(s, cont) {
619
+ var _scope = scope;
620
+ scope = s;
621
+ var ret = cont();
622
+ ret.scope = s;
623
+ scope = _scope;
624
+ return ret;
625
+ };
606
626
 
607
627
  function is_constant(node) {
608
628
  return node[0] == "string" || node[0] == "num";
@@ -667,7 +687,7 @@ function ast_squeeze(ast, options) {
667
687
 
668
688
  function clone(obj) {
669
689
  if (obj && obj.constructor == Array)
670
- return obj.map(clone);
690
+ return MAP(obj, clone);
671
691
  return obj;
672
692
  };
673
693
 
@@ -690,7 +710,9 @@ function ast_squeeze(ast, options) {
690
710
  };
691
711
 
692
712
  function _lambda(name, args, body) {
693
- return [ this[0], name, args, tighten(body.map(walk), "lambda") ];
713
+ return [ this[0], name, args, with_scope(body.scope, function(){
714
+ return tighten(MAP(body, walk), "lambda");
715
+ }) ];
694
716
  };
695
717
 
696
718
  // we get here for blocks that have been already transformed.
@@ -925,12 +947,14 @@ function ast_squeeze(ast, options) {
925
947
  },
926
948
  "if": make_if,
927
949
  "toplevel": function(body) {
928
- return [ "toplevel", tighten(body.map(walk)) ];
950
+ return [ "toplevel", with_scope(this.scope, function(){
951
+ return tighten(MAP(body, walk));
952
+ }) ];
929
953
  },
930
954
  "switch": function(expr, body) {
931
955
  var last = body.length - 1;
932
- return [ "switch", walk(expr), body.map(function(branch, i){
933
- var block = tighten(branch[1].map(walk));
956
+ return [ "switch", walk(expr), MAP(body, function(branch, i){
957
+ var block = tighten(MAP(branch[1], walk));
934
958
  if (i == last && block.length > 0) {
935
959
  var node = block[block.length - 1];
936
960
  if (node[0] == "break" && !node[1])
@@ -942,7 +966,7 @@ function ast_squeeze(ast, options) {
942
966
  "function": _lambda,
943
967
  "defun": _lambda,
944
968
  "block": function(body) {
945
- if (body) return rmblock([ "block", tighten(body.map(walk)) ]);
969
+ if (body) return rmblock([ "block", tighten(MAP(body, walk)) ]);
946
970
  },
947
971
  "binary": function(op, left, right) {
948
972
  left = walk(left);
@@ -975,17 +999,45 @@ function ast_squeeze(ast, options) {
975
999
  "try": function(t, c, f) {
976
1000
  return [
977
1001
  "try",
978
- tighten(t.map(walk)),
979
- c != null ? [ c[0], tighten(c[1].map(walk)) ] : null,
980
- f != null ? tighten(f.map(walk)) : null
1002
+ tighten(MAP(t, walk)),
1003
+ c != null ? [ c[0], tighten(MAP(c[1], walk)) ] : null,
1004
+ f != null ? tighten(MAP(f, walk)) : null
981
1005
  ];
982
1006
  },
983
1007
  "unary-prefix": function(op, cond) {
984
- if (op == "!")
1008
+ if (op == "!") {
1009
+ cond = walk(cond);
1010
+ if (cond[0] == "unary-prefix" && cond[1] == "!") {
1011
+ var p = w.parent();
1012
+ if (p[0] == "unary-prefix" && p[1] == "!")
1013
+ return cond[2];
1014
+ return [ "unary-prefix", "!", cond ];
1015
+ }
985
1016
  return best_of(this, negate(cond));
1017
+ }
1018
+ },
1019
+ "name": function(name) {
1020
+ switch (name) {
1021
+ case "true": return [ "unary-prefix", "!", [ "num", 0 ]];
1022
+ case "false": return [ "unary-prefix", "!", [ "num", 1 ]];
1023
+ }
1024
+ },
1025
+ "new": function(ctor, args) {
1026
+ if (ctor[0] == "name" && ctor[1] == "Array" && !scope.has("Array")) {
1027
+ if (args.length != 1) {
1028
+ return [ "array", args ];
1029
+ } else {
1030
+ return [ "call", [ "name", "Array" ], args ];
1031
+ }
1032
+ }
1033
+ },
1034
+ "call": function(expr, args) {
1035
+ if (expr[0] == "name" && expr[1] == "Array" && args.length != 1 && !scope.has("Array")) {
1036
+ return [ "array", args ];
1037
+ }
986
1038
  }
987
1039
  }, function() {
988
- return walk(ast);
1040
+ return walk(ast_add_scope(ast));
989
1041
  });
990
1042
  };
991
1043
 
@@ -1001,6 +1053,28 @@ var DOT_CALL_NO_PARENS = jsp.array_to_hash([
1001
1053
  "regexp"
1002
1054
  ]);
1003
1055
 
1056
+ function make_string(str) {
1057
+ var dq = 0, sq = 0;
1058
+ str = str.replace(/[\\\b\f\n\r\t\x22\x27]/g, function(s){
1059
+ switch (s) {
1060
+ case "\\": return "\\\\";
1061
+ case "\b": return "\\b";
1062
+ case "\f": return "\\f";
1063
+ case "\n": return "\\n";
1064
+ case "\r": return "\\r";
1065
+ case "\t": return "\\t";
1066
+ case '"': ++dq; return '"';
1067
+ case "'": ++sq; return "'";
1068
+ }
1069
+ return s;
1070
+ });
1071
+ if (dq > sq) {
1072
+ return "'" + str.replace(/\x27/g, "\\'") + "'";
1073
+ } else {
1074
+ return '"' + str.replace(/\x22/g, '\\"') + '"';
1075
+ }
1076
+ };
1077
+
1004
1078
  function gen_code(ast, beautify) {
1005
1079
  if (beautify) beautify = defaults(beautify, {
1006
1080
  indent_start : 0,
@@ -1120,10 +1194,10 @@ function gen_code(ast, beautify) {
1120
1194
  },
1121
1195
  "block": make_block,
1122
1196
  "var": function(defs) {
1123
- return "var " + add_commas(defs.map(make_1vardef)) + ";";
1197
+ return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
1124
1198
  },
1125
1199
  "const": function(defs) {
1126
- return "const " + add_commas(defs.map(make_1vardef)) + ";";
1200
+ return "const " + add_commas(MAP(defs, make_1vardef)) + ";";
1127
1201
  },
1128
1202
  "try": function(tr, ca, fi) {
1129
1203
  var out = [ "try", make_block(tr) ];
@@ -1135,7 +1209,7 @@ function gen_code(ast, beautify) {
1135
1209
  return add_spaces([ "throw", make(expr) ]) + ";";
1136
1210
  },
1137
1211
  "new": function(ctor, args) {
1138
- args = args.length > 0 ? "(" + add_commas(args.map(make)) + ")" : "";
1212
+ args = args.length > 0 ? "(" + add_commas(MAP(args, make)) + ")" : "";
1139
1213
  return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){
1140
1214
  var w = ast_walker(), has_call = {};
1141
1215
  try {
@@ -1189,7 +1263,9 @@ function gen_code(ast, beautify) {
1189
1263
  var f = make(func);
1190
1264
  if (needs_parens(func))
1191
1265
  f = "(" + f + ")";
1192
- return f + "(" + add_commas(args.map(make)) + ")";
1266
+ return f + "(" + add_commas(MAP(args, function(expr){
1267
+ return parenthesize(expr, "seq");
1268
+ })) + ")";
1193
1269
  },
1194
1270
  "function": make_function,
1195
1271
  "defun": make_function,
@@ -1265,7 +1341,12 @@ function gen_code(ast, beautify) {
1265
1341
  if (props.length == 0)
1266
1342
  return "{}";
1267
1343
  return "{" + newline + with_indent(function(){
1268
- return props.map(function(p){
1344
+ return MAP(props, function(p){
1345
+ if (p.length == 3) {
1346
+ // getter/setter. The name is in p[0], the arg.list in p[1][2], the
1347
+ // body in p[1][3] and type ("get" / "set") in p[2].
1348
+ return indent(make_function(p[0], p[1][2], p[1][3], p[2]));
1349
+ }
1269
1350
  var key = p[0], val = make(p[1]);
1270
1351
  if (beautify && beautify.quote_keys) {
1271
1352
  key = make_string(key);
@@ -1285,13 +1366,15 @@ function gen_code(ast, beautify) {
1285
1366
  },
1286
1367
  "array": function(elements) {
1287
1368
  if (elements.length == 0) return "[]";
1288
- return add_spaces([ "[", add_commas(elements.map(make)), "]" ]);
1369
+ return add_spaces([ "[", add_commas(MAP(elements, function(el){
1370
+ return parenthesize(el, "seq");
1371
+ })), "]" ]);
1289
1372
  },
1290
1373
  "stat": function(stmt) {
1291
1374
  return make(stmt).replace(/;*\s*$/, ";");
1292
1375
  },
1293
1376
  "seq": function() {
1294
- return add_commas(slice(arguments).map(make));
1377
+ return add_commas(MAP(slice(arguments), make));
1295
1378
  },
1296
1379
  "label": function(name, block) {
1297
1380
  return add_spaces([ make_name(name), ":", make(block) ]);
@@ -1341,39 +1424,16 @@ function gen_code(ast, beautify) {
1341
1424
  return make(th);
1342
1425
  };
1343
1426
 
1344
- function make_function(name, args, body) {
1345
- var out = "function";
1427
+ function make_function(name, args, body, keyword) {
1428
+ var out = keyword || "function";
1346
1429
  if (name) {
1347
1430
  out += " " + make_name(name);
1348
1431
  }
1349
- out += "(" + add_commas(args.map(make_name)) + ")";
1432
+ out += "(" + add_commas(MAP(args, make_name)) + ")";
1350
1433
  return add_spaces([ out, make_block(body) ]);
1351
1434
  };
1352
1435
 
1353
- function make_string(str) {
1354
- // return '"' +
1355
- // str.replace(/\x5c/g, "\\\\")
1356
- // .replace(/\r?\n/g, "\\n")
1357
- // .replace(/\t/g, "\\t")
1358
- // .replace(/\r/g, "\\r")
1359
- // .replace(/\f/g, "\\f")
1360
- // .replace(/[\b]/g, "\\b")
1361
- // .replace(/\x22/g, "\\\"")
1362
- // .replace(/[\x00-\x1f]|[\x80-\xff]/g, function(c){
1363
- // var hex = c.charCodeAt(0).toString(16);
1364
- // if (hex.length < 2)
1365
- // hex = "0" + hex;
1366
- // return "\\x" + hex;
1367
- // })
1368
- // + '"';
1369
- return JSON.stringify(str); // STILL cheating.
1370
- };
1371
-
1372
1436
  function make_name(name) {
1373
- switch (name) {
1374
- case "true": return beautify ? "true" : "!0";
1375
- case "false": return beautify ? "false" : "!1";
1376
- }
1377
1437
  return name.toString();
1378
1438
  };
1379
1439
 
@@ -1387,13 +1447,13 @@ function gen_code(ast, beautify) {
1387
1447
  a.push(code);
1388
1448
  }
1389
1449
  }
1390
- return a.map(indent);
1450
+ return MAP(a, indent);
1391
1451
  };
1392
1452
 
1393
1453
  function make_switch_block(body) {
1394
1454
  var n = body.length;
1395
1455
  if (n == 0) return "{}";
1396
- return "{" + newline + body.map(function(branch, i){
1456
+ return "{" + newline + MAP(body, function(branch, i){
1397
1457
  var has_body = branch[1].length > 0, code = with_indent(function(){
1398
1458
  return indent(branch[0]
1399
1459
  ? add_spaces([ "case", make(branch[0]) + ":" ])
@@ -1471,6 +1531,24 @@ function HOP(obj, prop) {
1471
1531
  return Object.prototype.hasOwnProperty.call(obj, prop);
1472
1532
  };
1473
1533
 
1534
+ // some utilities
1535
+
1536
+ var MAP;
1537
+
1538
+ (function(){
1539
+ MAP = function(a, f, o) {
1540
+ var ret = [];
1541
+ for (var i = 0; i < a.length; ++i) {
1542
+ var val = f.call(o, a[i], i);
1543
+ if (val instanceof AtTop) ret.unshift(val.v);
1544
+ else ret.push(val);
1545
+ }
1546
+ return ret;
1547
+ };
1548
+ MAP.at_top = function(val) { return new AtTop(val) };
1549
+ function AtTop(val) { this.v = val };
1550
+ })();
1551
+
1474
1552
  /* -----[ Exports ]----- */
1475
1553
 
1476
1554
  exports.ast_walker = ast_walker;
@@ -1479,3 +1557,4 @@ exports.ast_squeeze = ast_squeeze;
1479
1557
  exports.gen_code = gen_code;
1480
1558
  exports.ast_add_scope = ast_add_scope;
1481
1559
  exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more;
1560
+ exports.set_logger = function(logger) { warn = logger };
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: 23
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ville Lautanala
@@ -15,8 +15,8 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-24 00:00:00 +02:00
19
- default_executable:
18
+ date: 2011-01-06 00:00:00 +02:00
19
+ default_executable: uglify
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  requirement: &id001 !ruby/object:Gem::Requirement
@@ -24,12 +24,12 @@ dependencies:
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- hash: 9
27
+ hash: 63
28
28
  segments:
29
29
  - 0
30
- - 7
31
- - 5
32
- version: 0.7.5
30
+ - 8
31
+ - 0
32
+ version: 0.8.0
33
33
  type: :runtime
34
34
  name: therubyracer
35
35
  prerelease: false
@@ -40,12 +40,12 @@ dependencies:
40
40
  requirements:
41
41
  - - ~>
42
42
  - !ruby/object:Gem::Version
43
- hash: 15
43
+ hash: 3
44
44
  segments:
45
45
  - 2
46
+ - 3
46
47
  - 0
47
- - 0
48
- version: 2.0.0
48
+ version: 2.3.0
49
49
  type: :development
50
50
  name: rspec
51
51
  prerelease: false
@@ -72,13 +72,12 @@ dependencies:
72
72
  requirements:
73
73
  - - ~>
74
74
  - !ruby/object:Gem::Version
75
- hash: -1876988220
75
+ hash: 3
76
76
  segments:
77
77
  - 1
78
78
  - 5
79
79
  - 0
80
- - pre5
81
- version: 1.5.0.pre5
80
+ version: 1.5.0
82
81
  type: :development
83
82
  name: jeweler
84
83
  prerelease: false
@@ -178,8 +177,8 @@ dependencies:
178
177
  version_requirements: *id010
179
178
  description:
180
179
  email: lautis@gmail.com
181
- executables: []
182
-
180
+ executables:
181
+ - uglify
183
182
  extensions: []
184
183
 
185
184
  extra_rdoc_files:
@@ -194,7 +193,10 @@ files:
194
193
  - README.rdoc
195
194
  - Rakefile
196
195
  - VERSION
196
+ - bin/uglify
197
197
  - lib/uglifier.rb
198
+ - lib/uglifier/cli.rb
199
+ - lib/uglifier/node.rb
198
200
  - spec/spec_helper.rb
199
201
  - spec/uglifier_spec.rb
200
202
  - uglifier.gemspec