uglifier 3.0.2 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/.rubocop.yml +3 -3
- data/.travis.yml +8 -9
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -1
- data/README.md +2 -1
- data/Rakefile +3 -0
- data/lib/uglifier.rb +13 -3
- data/lib/uglifier/version.rb +1 -1
- data/lib/uglify.js +5 -5
- data/uglifier.gemspec +5 -3
- metadata +5 -14
- data/gemfiles/alaska +0 -4
- data/gemfiles/rubyracer +0 -4
- data/gemfiles/rubyrhino +0 -4
- data/spec/source_map_spec.rb +0 -226
- data/spec/spec_helper.rb +0 -32
- data/spec/uglifier_spec.rb +0 -380
data/spec/spec_helper.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
require 'uglifier'
|
3
|
-
require 'rspec'
|
4
|
-
require 'sourcemap'
|
5
|
-
|
6
|
-
# Requires supporting files with custom matchers and macros, etc,
|
7
|
-
# in ./support/ and its subdirectories.
|
8
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
9
|
-
|
10
|
-
if ENV["ALASKA"]
|
11
|
-
require 'alaska/runtime'
|
12
|
-
require 'tempfile'
|
13
|
-
ExecJS.runtime = Alaska::Runtime.new
|
14
|
-
end
|
15
|
-
|
16
|
-
RSpec.configure do |config|
|
17
|
-
config.mock_with :rspec do |mock|
|
18
|
-
mock.syntax = :expect
|
19
|
-
end
|
20
|
-
config.expect_with :rspec do |expect|
|
21
|
-
expect.syntax = :expect
|
22
|
-
end
|
23
|
-
|
24
|
-
if ENV['CI']
|
25
|
-
config.before(:example, :focus) { raise "Do not commit focused specs" }
|
26
|
-
else
|
27
|
-
config.filter_run_including :focus => true
|
28
|
-
config.run_all_when_everything_filtered = true
|
29
|
-
end
|
30
|
-
|
31
|
-
config.warnings = true
|
32
|
-
end
|
data/spec/uglifier_spec.rb
DELETED
@@ -1,380 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
require 'stringio'
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
4
|
-
|
5
|
-
describe "Uglifier" do
|
6
|
-
it "minifies JS" do
|
7
|
-
source = File.open("lib/uglify.js", "r:UTF-8").read
|
8
|
-
minified = Uglifier.new.compile(source)
|
9
|
-
expect(minified.length).to be < source.length
|
10
|
-
expect { Uglifier.new.compile(minified) }.not_to raise_error
|
11
|
-
end
|
12
|
-
|
13
|
-
it "throws an exception when compilation fails" do
|
14
|
-
expect { Uglifier.new.compile(")(") }.to raise_error(Uglifier::Error)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "throws an exception on invalid option" do
|
18
|
-
expect { Uglifier.new(:foo => true) }.to raise_error(ArgumentError)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "doesn't omit null character in strings" do
|
22
|
-
expect(Uglifier.new.compile('var foo="\0bar"')).to include("\\0bar")
|
23
|
-
end
|
24
|
-
|
25
|
-
it "adds trailing semicolon to minified source" do
|
26
|
-
source = "(function id(i) {return i;}());"
|
27
|
-
expect(Uglifier.new.compile(source)[-1]).to eql(";"[0])
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "property name mangling" do
|
31
|
-
let(:source) do
|
32
|
-
<<-JS
|
33
|
-
var obj = {
|
34
|
-
_hidden: false,
|
35
|
-
name: 'value'
|
36
|
-
};
|
37
|
-
|
38
|
-
alert(object.name);
|
39
|
-
JS
|
40
|
-
end
|
41
|
-
|
42
|
-
it "does not mangle property names by default" do
|
43
|
-
expect(Uglifier.compile(source)).to include("object.name")
|
44
|
-
end
|
45
|
-
|
46
|
-
it "can be configured to mangle properties" do
|
47
|
-
expect(Uglifier.compile(source, :mangle_properties => true))
|
48
|
-
.not_to include("object.name")
|
49
|
-
end
|
50
|
-
|
51
|
-
it "can configure a regex for mangling" do
|
52
|
-
expect(Uglifier.compile(source, :mangle_properties => { :regex => /^_/ }))
|
53
|
-
.to include("object.name")
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "argument name mangling" do
|
58
|
-
it "doesn't try to mangle $super by default to avoid breaking PrototypeJS" do
|
59
|
-
expect(Uglifier.compile('function foo($super) {return $super}')).to include("$super")
|
60
|
-
end
|
61
|
-
|
62
|
-
it "allows variables to be excluded from mangling" do
|
63
|
-
code = "function bar(foo) {return foo + 'bar'};"
|
64
|
-
expect(Uglifier.compile(code, :mangle => { :except => ["foo"] }))
|
65
|
-
.to include("(foo)")
|
66
|
-
end
|
67
|
-
|
68
|
-
it "skips mangling when set to false" do
|
69
|
-
code = "function bar(foo) {return foo + 'bar'};"
|
70
|
-
expect(Uglifier.compile(code, :mangle => false)).to include("(foo)")
|
71
|
-
end
|
72
|
-
|
73
|
-
it "mangles argument names by default" do
|
74
|
-
code = "function bar(foo) {return foo + 'bar'};"
|
75
|
-
expect(Uglifier.compile(code)).not_to include("(foo)")
|
76
|
-
end
|
77
|
-
|
78
|
-
it "mangles top-level names when explicitly instructed" do
|
79
|
-
code = "function bar(foo) {return foo + 'bar'};"
|
80
|
-
expect(Uglifier.compile(code, :mangle => { :toplevel => false }))
|
81
|
-
.to include("bar(")
|
82
|
-
expect(Uglifier.compile(code, :mangle => { :toplevel => true }))
|
83
|
-
.not_to include("bar(")
|
84
|
-
end
|
85
|
-
|
86
|
-
it "can be controlled with mangle option" do
|
87
|
-
code = "function bar(foo) {return foo + 'bar'};"
|
88
|
-
expect(Uglifier.compile(code, :mangle => false)).to include("(foo)")
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
describe "comment preservation" do
|
93
|
-
let(:source) do
|
94
|
-
<<-JS
|
95
|
-
/* @preserve Copyright Notice */
|
96
|
-
/* (c) 2011 */
|
97
|
-
// INCLUDED
|
98
|
-
//! BANG
|
99
|
-
function identity(p) { return p; }
|
100
|
-
/* Another Copyright */
|
101
|
-
/*! Another Bang */
|
102
|
-
// A comment!
|
103
|
-
function add(a, b) { return a + b; }
|
104
|
-
JS
|
105
|
-
end
|
106
|
-
|
107
|
-
it "handles copyright option" do
|
108
|
-
compiled = Uglifier.compile(source, :copyright => false)
|
109
|
-
expect(compiled).not_to match(/Copyright/)
|
110
|
-
end
|
111
|
-
|
112
|
-
describe ":copyright" do
|
113
|
-
subject { Uglifier.compile(source, :comments => :copyright) }
|
114
|
-
|
115
|
-
it "preserves comments with string Copyright" do
|
116
|
-
expect(subject).to match(/Copyright Notice/)
|
117
|
-
expect(subject).to match(/Another Copyright/)
|
118
|
-
end
|
119
|
-
|
120
|
-
it "preserves comments that start with a bang (!)" do
|
121
|
-
expect(subject).to match(/! BANG/)
|
122
|
-
expect(subject).to match(/! Another Bang/)
|
123
|
-
end
|
124
|
-
|
125
|
-
it "ignores other comments" do
|
126
|
-
expect(subject).not_to match(/INCLUDED/)
|
127
|
-
expect(subject).not_to match(/A comment!/)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe ":jsdoc" do
|
132
|
-
subject { Uglifier.compile(source, :output => { :comments => :jsdoc }) }
|
133
|
-
|
134
|
-
it "preserves jsdoc license/preserve blocks" do
|
135
|
-
expect(subject).to match(/Copyright Notice/)
|
136
|
-
end
|
137
|
-
|
138
|
-
it "ignores other comments" do
|
139
|
-
expect(subject).not_to match(/Another Copyright/)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
describe ":all" do
|
144
|
-
subject { Uglifier.compile(source, :comments => :all) }
|
145
|
-
|
146
|
-
it "preserves all comments" do
|
147
|
-
expect(subject).to match(/INCLUDED/)
|
148
|
-
expect(subject).to match(/2011/)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
describe ":none" do
|
153
|
-
subject { Uglifier.compile(source, :comments => :none) }
|
154
|
-
|
155
|
-
it "omits all comments" do
|
156
|
-
expect(subject).not_to match(%r{//})
|
157
|
-
expect(subject).not_to match(%r{/\*})
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
describe "regular expression" do
|
162
|
-
subject { Uglifier.compile(source, :comments => /included/i) }
|
163
|
-
|
164
|
-
it "matches comment blocks with regex" do
|
165
|
-
expect(subject).to match(/INCLUDED/)
|
166
|
-
end
|
167
|
-
|
168
|
-
it "omits other blocks" do
|
169
|
-
expect(subject).not_to match(/2011/)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
it "squeezes code only if squeeze is set to true" do
|
175
|
-
code = "function a(a){if(a) { return 0; } else { return 1; }}"
|
176
|
-
minified = Uglifier.compile(code, :squeeze => false)
|
177
|
-
squeezed = Uglifier.compile(code, :squeeze => true)
|
178
|
-
expect(minified.length).to be > squeezed.length
|
179
|
-
end
|
180
|
-
|
181
|
-
it "honors max line length" do
|
182
|
-
code = "var foo = 123;function bar() { return foo; }"
|
183
|
-
uglifier = Uglifier.new(:output => { :max_line_len => 20 }, :compress => false)
|
184
|
-
expect(uglifier.compile(code).split("\n").map(&:length)).to all(be < 28)
|
185
|
-
end
|
186
|
-
|
187
|
-
it "hoists vars to top of the scope" do
|
188
|
-
code = "function something() { var a = 1; a = 2; var b = 3; return a + b;}"
|
189
|
-
minified = Uglifier.compile(code, :compress => { :hoist_vars => true })
|
190
|
-
expect(minified).to match(/var \w,\w/)
|
191
|
-
end
|
192
|
-
|
193
|
-
describe "screw_ie8 option" do
|
194
|
-
let(:code) { "function something() { return g['switch']; }" }
|
195
|
-
|
196
|
-
it "defaults to not screw IE8" do
|
197
|
-
expect(Uglifier.compile(code)).to match(".switch")
|
198
|
-
end
|
199
|
-
|
200
|
-
it "forwards screw_ie8 option to UglifyJS" do
|
201
|
-
expect(Uglifier.compile(code, :mangle => false, :screw_ie8 => true)).to match(/g\.switch/)
|
202
|
-
expect(Uglifier.compile(code, :compress => false, :screw_ie8 => true)).to match(/g\.switch/)
|
203
|
-
end
|
204
|
-
|
205
|
-
it "supports legacy ie_proof output option as opposite for screw_ie8" do
|
206
|
-
minified = Uglifier.compile(code, :output => { :ie_proof => true })
|
207
|
-
expect(minified).to include('["switch"]')
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
it "can be configured to output only ASCII" do
|
212
|
-
code = "function emoji() { return '\\ud83c\\ude01'; }"
|
213
|
-
minified = Uglifier.compile(code, :output => { :ascii_only => true })
|
214
|
-
expect(minified).to include("\\ud83c\\ude01")
|
215
|
-
end
|
216
|
-
|
217
|
-
it "escapes </script when asked to" do
|
218
|
-
code = "function test() { return '</script>';}"
|
219
|
-
minified = Uglifier.compile(code, :output => { :inline_script => true })
|
220
|
-
expect(minified).not_to include("</script>")
|
221
|
-
end
|
222
|
-
|
223
|
-
it "quotes keys" do
|
224
|
-
code = "var a = {foo: 1}"
|
225
|
-
minified = Uglifier.compile(code, :output => { :quote_keys => true })
|
226
|
-
expect(minified).to include('"foo"')
|
227
|
-
end
|
228
|
-
|
229
|
-
it "quotes unsafe keys by default" do
|
230
|
-
code = 'var code = {"class": "", "\u200c":"A"}'
|
231
|
-
expect(Uglifier.compile(code)).to include('"class"')
|
232
|
-
expect(Uglifier.compile(code)).to include('"\u200c"')
|
233
|
-
|
234
|
-
uglifier = Uglifier.new(:output => { :ascii_only => false, :quote_keys => false })
|
235
|
-
expect(uglifier.compile(code)).to include(["200c".to_i(16)].pack("U*"))
|
236
|
-
end
|
237
|
-
|
238
|
-
it "handles constant definitions" do
|
239
|
-
code = "if (BOOL) { var a = STR; var b = NULL; var c = NUM; }"
|
240
|
-
defines = { "NUM" => 1234, "BOOL" => true, "NULL" => nil, "STR" => "str" }
|
241
|
-
processed = Uglifier.compile(code, :define => defines)
|
242
|
-
expect(processed).to include("a=\"str\"")
|
243
|
-
expect(processed).not_to include("if")
|
244
|
-
expect(processed).to include("b=null")
|
245
|
-
expect(processed).to include("c=1234")
|
246
|
-
end
|
247
|
-
|
248
|
-
it "can disable IIFE negation" do
|
249
|
-
code = "(function() { console.log('test')})();"
|
250
|
-
disabled_negation = Uglifier.compile(code, :compress => { :negate_iife => false })
|
251
|
-
expect(disabled_negation).not_to include("!")
|
252
|
-
negation = Uglifier.compile(code, :compress => { :negate_iife => true })
|
253
|
-
expect(negation).to include("!")
|
254
|
-
end
|
255
|
-
|
256
|
-
it "can drop console logging" do
|
257
|
-
code = "(function() { console.log('test')})();"
|
258
|
-
compiled = Uglifier.compile(code, :compress => { :drop_console => true })
|
259
|
-
expect(compiled).not_to include("console")
|
260
|
-
end
|
261
|
-
|
262
|
-
describe "collapse_vars option" do
|
263
|
-
let(:code) do
|
264
|
-
<<-JS
|
265
|
-
function a() {
|
266
|
-
var win = window;
|
267
|
-
return win.Handlebars;
|
268
|
-
}
|
269
|
-
JS
|
270
|
-
end
|
271
|
-
|
272
|
-
it "collapses vars when collapse_vars is enabled" do
|
273
|
-
compiled = Uglifier.compile(code, :compress => { :collapse_vars => true })
|
274
|
-
expect(compiled).to include("return window.Handlebars")
|
275
|
-
end
|
276
|
-
|
277
|
-
it "defaults to not collapsing variables" do
|
278
|
-
expect(Uglifier.compile(code)).not_to include("return window.Handlebars")
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
it "processes @ngInject annotations" do
|
283
|
-
code = <<-JS
|
284
|
-
/**
|
285
|
-
* @ngInject
|
286
|
-
*/
|
287
|
-
var f = function(foo, bar) { return foo + bar};
|
288
|
-
JS
|
289
|
-
with_angular = Uglifier.compile(code, :compress => { :angular => true })
|
290
|
-
without_angular = Uglifier.compile(code, :compress => { :angular => false })
|
291
|
-
expect(with_angular).to include("f.$inject")
|
292
|
-
expect(without_angular).not_to include("f.$inject")
|
293
|
-
end
|
294
|
-
|
295
|
-
it "keeps unused function arguments when keep_fargs option is set" do
|
296
|
-
code = <<-JS
|
297
|
-
function plus(a, b, c) { return a + b};
|
298
|
-
plus(1, 2);
|
299
|
-
JS
|
300
|
-
|
301
|
-
options = lambda do |keep_fargs|
|
302
|
-
{
|
303
|
-
:mangle => false,
|
304
|
-
:compress => {
|
305
|
-
:keep_fargs => keep_fargs,
|
306
|
-
:unsafe => true
|
307
|
-
}
|
308
|
-
}
|
309
|
-
end
|
310
|
-
|
311
|
-
expect(Uglifier.compile(code, options.call(false))).not_to include("c)")
|
312
|
-
expect(Uglifier.compile(code, options.call(true))).to include("c)")
|
313
|
-
end
|
314
|
-
|
315
|
-
it "keeps function names in output when compressor keep_fnames is set" do
|
316
|
-
code = <<-JS
|
317
|
-
(function plus(a, b) { return a + b})(1, 2);
|
318
|
-
JS
|
319
|
-
expect(Uglifier.compile(code, :compress => true)).not_to include("plus")
|
320
|
-
|
321
|
-
keep_fnames = Uglifier.compile(code, :mangle => false, :compress => { :keep_fnames => true })
|
322
|
-
expect(keep_fnames).to include("plus")
|
323
|
-
end
|
324
|
-
|
325
|
-
it "does not mangle function names in output when mangler keep_fnames is set" do
|
326
|
-
code = <<-JS
|
327
|
-
(function() {
|
328
|
-
function plus(a, b) { return a + b}
|
329
|
-
plus(1, 2);
|
330
|
-
})();
|
331
|
-
JS
|
332
|
-
expect(Uglifier.compile(code, :mangle => true)).not_to include("plus")
|
333
|
-
|
334
|
-
keep_fnames = Uglifier.compile(code, :mangle => { :keep_fnames => true })
|
335
|
-
expect(keep_fnames).to include("plus")
|
336
|
-
end
|
337
|
-
|
338
|
-
it "sets sets both compress and mangle keep_fnames when toplevel keep_fnames is true" do
|
339
|
-
code = <<-JS
|
340
|
-
(function plus(a, b) { return a + b})(1, 2);
|
341
|
-
JS
|
342
|
-
expect(Uglifier.compile(code)).not_to include("plus")
|
343
|
-
|
344
|
-
keep_fnames = Uglifier.compile(code, :keep_fnames => true)
|
345
|
-
expect(keep_fnames).to include("plus")
|
346
|
-
end
|
347
|
-
|
348
|
-
describe "Input Formats" do
|
349
|
-
let(:code) { "function hello() { return 'hello world'; }" }
|
350
|
-
|
351
|
-
it "handles strings" do
|
352
|
-
expect(Uglifier.new.compile(code)).not_to be_empty
|
353
|
-
end
|
354
|
-
|
355
|
-
it "handles IO objects" do
|
356
|
-
expect(Uglifier.new.compile(StringIO.new(code))).not_to be_empty
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
describe "enclose" do
|
361
|
-
let(:code) { "$.foo()" }
|
362
|
-
|
363
|
-
it "encloses code with given arguments" do
|
364
|
-
minified = Uglifier.compile(code, :enclose => { 'window.jQuery' => '$' })
|
365
|
-
expect(minified).to match(/window.jQuery/)
|
366
|
-
end
|
367
|
-
|
368
|
-
it "handles multiple definitions" do
|
369
|
-
definitions = [%w(lol lulz), %w(foo bar)]
|
370
|
-
minified = Uglifier.compile(code, :enclose => definitions)
|
371
|
-
expect(minified).to match(/lol,foo/)
|
372
|
-
expect(minified).to match(/lulz,bar/)
|
373
|
-
end
|
374
|
-
|
375
|
-
it "wraps with function when given empty object" do
|
376
|
-
minified = Uglifier.compile(code, :enclose => {})
|
377
|
-
expect(minified).to match(/function\(/)
|
378
|
-
end
|
379
|
-
end
|
380
|
-
end
|