uglifier 0.1.1 → 0.2.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/VERSION +1 -1
- data/lib/uglifier.rb +33 -19
- data/spec/uglifier_spec.rb +15 -0
- data/uglifier.gemspec +4 -3
- data/vendor/uglifyjs/lib/process.js +14 -17
- data/vendor/uglifyjs/lib/squeeze-more.js +22 -0
- metadata +6 -5
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/uglifier.rb
CHANGED
@@ -11,6 +11,7 @@ class Uglifier
|
|
11
11
|
:seqs => true, # Reduce consecutive statements in blocks into single statement
|
12
12
|
:dead_code => true, # Remove dead code (e.g. after return)
|
13
13
|
:extra => false, # Additional and potentially unsafe optimizations
|
14
|
+
:unsafe => false, # Optimizations known to be unsafe in some situations
|
14
15
|
:beautify => false, # Ouput indented code
|
15
16
|
:beautify_options => {
|
16
17
|
:indent_level => 4,
|
@@ -21,12 +22,20 @@ class Uglifier
|
|
21
22
|
}
|
22
23
|
|
23
24
|
def initialize(options = {})
|
24
|
-
@options = DEFAULTS.merge
|
25
|
+
@options = DEFAULTS.merge(options)
|
26
|
+
@exports = {
|
27
|
+
"sys" => {
|
28
|
+
:debug => lambda {|m| puts m }
|
29
|
+
}
|
30
|
+
}
|
25
31
|
end
|
26
32
|
|
27
33
|
def compile(source)
|
28
34
|
V8::Context.new do |cxt|
|
29
|
-
|
35
|
+
cxt["process"] = { :version => "v0.2.0" }
|
36
|
+
|
37
|
+
load_file(cxt, "parse-js")
|
38
|
+
load_file(cxt, "process")
|
30
39
|
begin
|
31
40
|
return generate_code(cxt, ast(cxt, source))
|
32
41
|
rescue Exception => e
|
@@ -35,6 +44,10 @@ class Uglifier
|
|
35
44
|
end
|
36
45
|
end
|
37
46
|
|
47
|
+
def self.compile(source, options = {})
|
48
|
+
self.new(options).compile(source)
|
49
|
+
end
|
50
|
+
|
38
51
|
private
|
39
52
|
|
40
53
|
def generate_code(cxt, ast)
|
@@ -42,14 +55,17 @@ class Uglifier
|
|
42
55
|
end
|
43
56
|
|
44
57
|
def ast(cxt, source)
|
45
|
-
squeeze(cxt, mangle(cxt, cxt["parse"].call(source)))
|
58
|
+
squeeze_unsafe(cxt, squeeze(cxt, mangle(cxt, cxt["parse"].call(source))))
|
46
59
|
end
|
47
60
|
|
48
61
|
def mangle(cxt, ast)
|
62
|
+
return ast unless @options[:mangle]
|
49
63
|
cxt["ast_mangle"].call(ast, @options[:toplevel])
|
50
64
|
end
|
51
65
|
|
52
66
|
def squeeze(cxt, ast)
|
67
|
+
return ast unless @options[:squeeze]
|
68
|
+
|
53
69
|
cxt["ast_squeeze"].call(ast, {
|
54
70
|
"make_seqs" => @options[:seqs],
|
55
71
|
"dead_code" => @options[:dead_code],
|
@@ -57,25 +73,23 @@ class Uglifier
|
|
57
73
|
})
|
58
74
|
end
|
59
75
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
"sys" => {
|
64
|
-
:debug => lambda { |m| puts m }
|
65
|
-
},
|
66
|
-
"./parse-js" => load_file(cxt, "vendor/uglifyjs/lib/parse-js.js")
|
67
|
-
}
|
68
|
-
|
69
|
-
cxt["require"] = lambda do |file|
|
70
|
-
exports[file]
|
71
|
-
end
|
72
|
-
|
73
|
-
load_file(cxt, "vendor/uglifyjs/lib/process.js")
|
76
|
+
def squeeze_unsafe(cxt, ast)
|
77
|
+
return ast unless @options[:unsafe]
|
78
|
+
cxt["ast_squeeze_more"].call(ast)
|
74
79
|
end
|
75
80
|
|
76
81
|
def load_file(cxt, file)
|
82
|
+
old = cxt["exports"]
|
77
83
|
cxt["exports"] = {}
|
78
|
-
cxt
|
79
|
-
|
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]
|
80
94
|
end
|
81
95
|
end
|
data/spec/uglifier_spec.rb
CHANGED
@@ -25,4 +25,19 @@ describe "Uglifier" do
|
|
25
25
|
}")
|
26
26
|
}.should_not raise_error(Uglifier::Error)
|
27
27
|
end
|
28
|
+
|
29
|
+
it "does additional squeezing when unsafe options is true" do
|
30
|
+
unsafe_input = "function a(b){b.toString();}"
|
31
|
+
Uglifier.new(:unsafe => true).compile(unsafe_input).length.should < Uglifier.new(:unsafe => false).compile(unsafe_input).length
|
32
|
+
end
|
33
|
+
|
34
|
+
it "mangles variables only if mangle is set to true" do
|
35
|
+
code = "function longFunctionName(){}"
|
36
|
+
Uglifier.new(:mangle => false).compile(code).length.should == code.length
|
37
|
+
end
|
38
|
+
|
39
|
+
it "squeezes code only if squeeze is set to true" do
|
40
|
+
code = "function a(a){if(a) { return 0; } else { return 1; }}"
|
41
|
+
Uglifier.compile(code, :squeeze => false).length.should > Uglifier.compile(code, :squeeze => true).length
|
42
|
+
end
|
28
43
|
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.
|
8
|
+
s.version = "0.2.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-
|
12
|
+
s.date = %q{2010-11-24}
|
13
13
|
s.email = %q{lautis@gmail.com}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE.txt",
|
@@ -29,7 +29,8 @@ Gem::Specification.new do |s|
|
|
29
29
|
"spec/uglifier_spec.rb",
|
30
30
|
"uglifier.gemspec",
|
31
31
|
"vendor/uglifyjs/lib/parse-js.js",
|
32
|
-
"vendor/uglifyjs/lib/process.js"
|
32
|
+
"vendor/uglifyjs/lib/process.js",
|
33
|
+
"vendor/uglifyjs/lib/squeeze-more.js"
|
33
34
|
]
|
34
35
|
s.homepage = %q{http://github.com/lautis/uglifier}
|
35
36
|
s.require_paths = ["lib"]
|
@@ -361,14 +361,10 @@ function ast_add_scope(ast) {
|
|
361
361
|
|
362
362
|
function with_new_scope(cont) {
|
363
363
|
current_scope = new Scope(current_scope);
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
}
|
369
|
-
finally {
|
370
|
-
current_scope = current_scope.parent;
|
371
|
-
}
|
364
|
+
var ret = current_scope.body = cont();
|
365
|
+
ret.scope = current_scope;
|
366
|
+
current_scope = current_scope.parent;
|
367
|
+
return ret;
|
372
368
|
};
|
373
369
|
|
374
370
|
function define(name) {
|
@@ -987,17 +983,10 @@ function ast_squeeze(ast, options) {
|
|
987
983
|
"unary-prefix": function(op, cond) {
|
988
984
|
if (op == "!")
|
989
985
|
return best_of(this, negate(cond));
|
990
|
-
},
|
991
|
-
"call": function(expr, args) {
|
992
|
-
if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
|
993
|
-
// foo.toString() ==> foo+""
|
994
|
-
return [ "binary", "+", expr[1], [ "string", "" ]];
|
995
|
-
}
|
996
986
|
}
|
997
987
|
}, function() {
|
998
988
|
return walk(ast);
|
999
989
|
});
|
1000
|
-
|
1001
990
|
};
|
1002
991
|
|
1003
992
|
/* -----[ re-generate code from the AST ]----- */
|
@@ -1091,7 +1080,7 @@ function gen_code(ast, beautify) {
|
|
1091
1080
|
// parent is "stat", and so on. Messy stuff,
|
1092
1081
|
// but it worths the trouble.
|
1093
1082
|
var a = slice($stack), self = a.pop(), p = a.pop();
|
1094
|
-
while (
|
1083
|
+
while (p) {
|
1095
1084
|
if (p[0] == "stat") return true;
|
1096
1085
|
if ((p[0] == "seq" && p[1] === self) ||
|
1097
1086
|
(p[0] == "call" && p[1] === self) ||
|
@@ -1115,7 +1104,7 @@ function gen_code(ast, beautify) {
|
|
1115
1104
|
a.push(m[1] + "e" + m[2].length);
|
1116
1105
|
}
|
1117
1106
|
} else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
|
1118
|
-
a.push(m[2] + "e-" + (m[1].length +
|
1107
|
+
a.push(m[2] + "e-" + (m[1].length + m[2].length),
|
1119
1108
|
str.substr(str.indexOf(".")));
|
1120
1109
|
}
|
1121
1110
|
return best_of(a);
|
@@ -1329,6 +1318,13 @@ function gen_code(ast, beautify) {
|
|
1329
1318
|
// to the inner IF). This function checks for this case and
|
1330
1319
|
// adds the block brackets if needed.
|
1331
1320
|
function make_then(th) {
|
1321
|
+
if (th[0] == "do") {
|
1322
|
+
// https://github.com/mishoo/UglifyJS/issues/#issue/57
|
1323
|
+
// IE croaks with "syntax error" on code like this:
|
1324
|
+
// if (foo) do ... while(cond); else ...
|
1325
|
+
// we need block brackets around do/while
|
1326
|
+
return make([ "block", [ th ]]);
|
1327
|
+
}
|
1332
1328
|
var b = th;
|
1333
1329
|
while (true) {
|
1334
1330
|
var type = b[0];
|
@@ -1482,3 +1478,4 @@ exports.ast_mangle = ast_mangle;
|
|
1482
1478
|
exports.ast_squeeze = ast_squeeze;
|
1483
1479
|
exports.gen_code = gen_code;
|
1484
1480
|
exports.ast_add_scope = ast_add_scope;
|
1481
|
+
exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
var jsp = require("./parse-js"),
|
2
|
+
pro = require("./process"),
|
3
|
+
slice = jsp.slice,
|
4
|
+
member = jsp.member,
|
5
|
+
PRECEDENCE = jsp.PRECEDENCE,
|
6
|
+
OPERATORS = jsp.OPERATORS;
|
7
|
+
|
8
|
+
function ast_squeeze_more(ast) {
|
9
|
+
var w = pro.ast_walker(), walk = w.walk;
|
10
|
+
return w.with_walkers({
|
11
|
+
"call": function(expr, args) {
|
12
|
+
if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
|
13
|
+
// foo.toString() ==> foo+""
|
14
|
+
return [ "binary", "+", expr[1], [ "string", "" ]];
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}, function() {
|
18
|
+
return walk(ast);
|
19
|
+
});
|
20
|
+
};
|
21
|
+
|
22
|
+
exports.ast_squeeze_more = ast_squeeze_more;
|
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:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ville Lautanala
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-24 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -200,6 +200,7 @@ files:
|
|
200
200
|
- uglifier.gemspec
|
201
201
|
- vendor/uglifyjs/lib/parse-js.js
|
202
202
|
- vendor/uglifyjs/lib/process.js
|
203
|
+
- vendor/uglifyjs/lib/squeeze-more.js
|
203
204
|
has_rdoc: true
|
204
205
|
homepage: http://github.com/lautis/uglifier
|
205
206
|
licenses: []
|