uglifier 2.7.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,12 @@
2
2
  require 'stringio'
3
3
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
 
5
+ def expect_to_have_inline_source_map(minified, original)
6
+ options = { :source_map => { :sources_content => true } }
7
+ _, map = Uglifier.compile_with_map(minified, options)
8
+ expect(JSON.load(map).fetch("sourcesContent", [])).to include(original)
9
+ end
10
+
5
11
  describe "Uglifier" do
6
12
  let(:source) do
7
13
  <<-JS
@@ -24,20 +30,24 @@ describe "Uglifier" do
24
30
  end
25
31
 
26
32
  it "generates source maps with the correct meta-data" do
27
- _, map = Uglifier.compile_with_map(source,
28
- :source_filename => "ahoy.js",
29
- :output_filename => "ahoy.min.js",
30
- :source_root => "http://localhost/")
33
+ _, json = Uglifier.compile_with_map(
34
+ source,
35
+ :source_map => {
36
+ :filename => "ahoy.js",
37
+ :output_filename => "ahoy.min.js",
38
+ :root => "http://localhost/"
39
+ }
40
+ )
31
41
 
32
- map = SourceMap.from_s(map)
33
- expect(map.file).to eq("ahoy.min.js")
42
+ map = SourceMap::Map.from_json(json)
43
+ expect(map.filename).to eq("ahoy.min.js")
34
44
  expect(map.sources).to eq(["ahoy.js"])
35
45
  expect(map.names).to eq(%w(hello world))
36
- expect(map.source_root).to eq("http://localhost/")
37
- expect(map.mappings.first[:generated_line]).to eq(1)
46
+ expect(JSON.load(json)["sourceRoot"]).to eq("http://localhost/")
47
+ expect(map[0].generated.line).to eq(1)
38
48
  end
39
49
 
40
- it "should skip copyright lines in source maps" do
50
+ it "skips copyright lines in source maps" do
41
51
  source = <<-JS
42
52
  /* @copyright Conrad Irwin */
43
53
  function hello () {
@@ -49,14 +59,19 @@ describe "Uglifier" do
49
59
  };
50
60
  JS
51
61
 
52
- _, map = Uglifier.compile_with_map(source,
53
- :source_filename => "ahoy.js",
54
- :source_root => "http://localhost/")
55
- map = SourceMap.from_s(map)
56
- expect(map.mappings.first[:generated_line]).to eq(2)
62
+ _, json = Uglifier.compile_with_map(
63
+ source,
64
+ :source_map => {
65
+ :filename => "ahoy.js",
66
+ :root => "http://localhost/"
67
+ }
68
+ )
69
+
70
+ map = SourceMap::Map.from_json(json)
71
+ expect(map[0].generated.line).to eq(2)
57
72
  end
58
73
 
59
- it "should be able to handle an input source map" do
74
+ it "proceses an input source map" do
60
75
  source = <<-JS
61
76
  function hello () {
62
77
  function world () {
@@ -69,42 +84,143 @@ describe "Uglifier" do
69
84
 
70
85
  minified1, map1 = Uglifier.compile_with_map(
71
86
  source,
72
- :source_filename => "ahoy.js",
73
- :source_root => "http://localhost/",
87
+ :source_map => {
88
+ :filename => "ahoy.js",
89
+ :root => "http://localhost/"
90
+ },
74
91
  :mangle => false
75
92
  )
76
93
 
77
- _, map2 = Uglifier.compile_with_map(source,
78
- :input_source_map => map1,
79
- :mangle => true)
94
+ _, map2 = Uglifier.compile_with_map(
95
+ source,
96
+ :source_map => {
97
+ :input_source_map => map1
98
+ },
99
+ :mangle => true
100
+ )
80
101
 
81
102
  expect(minified1.lines.to_a.length).to eq(1)
82
103
 
83
- map = SourceMap.from_s(map2)
84
- expect(map.sources).to eq(["ahoy.js", "http://localhost/ahoy.js"])
85
- expect(map.mappings.first[:source_line]).to eq(1)
86
- expect(map.mappings.last[:source_line]).to eq(6)
104
+ map = SourceMap::Map.from_json(map2)
105
+ expect(map.sources).to eq(["http://localhost/ahoy.js"])
106
+ expect(map[0].generated.line).to eq(1)
107
+ expect(map[-1].original.line).to eq(1)
108
+ end
109
+
110
+ it "handles empty string as input map sourceRoot" do
111
+ _, map1 = Uglifier.compile_with_map(
112
+ source,
113
+ :source_map => {
114
+ :filename => "ahoy.js",
115
+ :root => ""
116
+ },
117
+ :mangle => false
118
+ )
119
+
120
+ _, map = Uglifier.compile_with_map(
121
+ source,
122
+ :source_map => {
123
+ :input_source_map => map1
124
+ },
125
+ :mangle => true
126
+ )
127
+
128
+ expect(SourceMap::Map.from_json(map).sources).to eq(["ahoy.js"])
87
129
  end
88
130
 
89
- it "appens source map url" do
90
- minified, _ = Uglifier.compile_with_map(
131
+ it "appends source map url to minified JS" do
132
+ minified, = Uglifier.compile_with_map(
91
133
  source,
92
- :source_filename => "ahoy.js",
93
- :output_filename => "ahoy.min.js",
94
- :source_root => "http://localhost/",
95
- :source_map_url => "http://example.com/map"
134
+ :source_map => {
135
+ :filename => "ahoy.js",
136
+ :output_filename => "ahoy.min.js",
137
+ :root => "http://localhost/",
138
+ :map_url => "http://example.com/map"
139
+ }
96
140
  )
97
141
  expect(minified).to include("\n//# sourceMappingURL=http://example.com/map")
98
142
  end
99
143
 
100
- it "appens source url" do
101
- minified, _ = Uglifier.compile_with_map(
144
+ it "appends source url to minified JS" do
145
+ minified, = Uglifier.compile_with_map(
102
146
  source,
103
- :source_filename => "ahoy.js",
104
- :output_filename => "ahoy.min.js",
105
- :source_root => "http://localhost/",
106
- :source_url => "http://example.com/source"
147
+ :source_map => {
148
+ :filename => "ahoy.js",
149
+ :output_filename => "ahoy.min.js",
150
+ :root => "http://localhost/",
151
+ :url => "http://example.com/source"
152
+ }
107
153
  )
108
154
  expect(minified).to include("\n//# sourceURL=http://example.com/source")
109
155
  end
156
+
157
+ it "inlines source map" do
158
+ minified = Uglifier.compile(
159
+ source,
160
+ :source_map => {
161
+ :filename => "ahoy.js",
162
+ :output_filename => "ahoy.min.js",
163
+ :root => "http://localhost/",
164
+ :url => "http://example.com/source"
165
+ }
166
+ )
167
+ source_map_mime = "application/json;charset=utf-8;base64,"
168
+ expect(minified).to include("\n//# sourceMappingURL=data:#{source_map_mime}")
169
+ end
170
+
171
+ describe "inline source map parsing" do
172
+ let(:minified) do
173
+ Uglifier.compile(
174
+ source,
175
+ :source_map => {
176
+ :filename => "ahoy.js",
177
+ :sources_content => true
178
+ }
179
+ )
180
+ end
181
+
182
+ let(:code) { minified.split("\n")[0] }
183
+ let(:source_mapping_url) { minified.split("\n")[1][2..-1] }
184
+
185
+ it "parses inline source maps from line comments" do
186
+ minified = "#{code}\n//#{source_mapping_url}"
187
+ expect_to_have_inline_source_map(minified, source)
188
+ end
189
+
190
+ it "parses inline source maps with block comments" do
191
+ minified = "#{code}\n/*#{source_mapping_url}*/"
192
+ expect_to_have_inline_source_map(minified, source)
193
+ end
194
+
195
+ it "parses inline source maps with multi-line block comments" do
196
+ minified = "#{code}\n/*\n#{source_mapping_url}\n*/"
197
+ expect_to_have_inline_source_map(minified, source)
198
+ end
199
+
200
+ it "parses inline source maps from mixed comments" do
201
+ minified = "#{code}\n/*\n//#{source_mapping_url}\n*/"
202
+ expect_to_have_inline_source_map(minified, source)
203
+ end
204
+
205
+ it "only parses source maps at end of file" do
206
+ minified = "#{code}\n//#{source_mapping_url}\nhello();"
207
+ _, map = Uglifier.compile_with_map(minified)
208
+ expect(JSON.load(map)["sourcesContent"]).to be_nil
209
+ end
210
+
211
+ it "handles other source map declarations at end of file" do
212
+ minified = "#{code}\n
213
+ //#{source_mapping_url}\n
214
+ //# sourceURL=http://example.com/source.js
215
+ //# sourceURL=http://example.com/source.js
216
+ "
217
+ expect_to_have_inline_source_map(minified, source)
218
+ end
219
+
220
+ it "does not explode when data URI is invalid" do
221
+ minified = "#{code}\n//# sourceMappingURL=data:application/javascript,foobar"
222
+ _, map = Uglifier.compile_with_map(minified)
223
+ expect(JSON.load(map)["sourcesContent"]).to be_nil
224
+ end
225
+ end
110
226
  end
@@ -1,14 +1,14 @@
1
1
  # encoding: UTF-8
2
2
  require 'uglifier'
3
3
  require 'rspec'
4
- require 'source_map'
4
+ require 'sourcemap'
5
5
 
6
6
  # Requires supporting files with custom matchers and macros, etc,
7
7
  # in ./support/ and its subdirectories.
8
8
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
9
9
 
10
10
  if ENV["ALASKA"]
11
- require 'alaska'
11
+ require 'alaska/runtime'
12
12
  require 'tempfile'
13
13
  ExecJS.runtime = Alaska::Runtime.new
14
14
  end
@@ -20,4 +20,13 @@ RSpec.configure do |config|
20
20
  config.expect_with :rspec do |expect|
21
21
  expect.syntax = :expect
22
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
23
32
  end
@@ -27,6 +27,33 @@ describe "Uglifier" do
27
27
  expect(Uglifier.new.compile(source)[-1]).to eql(";"[0])
28
28
  end
29
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
+
30
57
  describe "argument name mangling" do
31
58
  it "doesn't try to mangle $super by default to avoid breaking PrototypeJS" do
32
59
  expect(Uglifier.compile('function foo($super) {return $super}')).to include("$super")
@@ -34,7 +61,8 @@ describe "Uglifier" do
34
61
 
35
62
  it "allows variables to be excluded from mangling" do
36
63
  code = "function bar(foo) {return foo + 'bar'};"
37
- expect(Uglifier.compile(code, :mangle => { :except => ["foo"] })).to include("(foo)")
64
+ expect(Uglifier.compile(code, :mangle => { :except => ["foo"] }))
65
+ .to include("(foo)")
38
66
  end
39
67
 
40
68
  it "skips mangling when set to false" do
@@ -42,21 +70,28 @@ describe "Uglifier" do
42
70
  expect(Uglifier.compile(code, :mangle => false)).to include("(foo)")
43
71
  end
44
72
 
45
- it "mangles argumen names by default" do
73
+ it "mangles argument names by default" do
46
74
  code = "function bar(foo) {return foo + 'bar'};"
47
- expect(Uglifier.compile(code, :mangle => true)).not_to include("(foo)")
75
+ expect(Uglifier.compile(code)).not_to include("(foo)")
48
76
  end
49
77
 
50
78
  it "mangles top-level names when explicitly instructed" do
51
79
  code = "function bar(foo) {return foo + 'bar'};"
52
- expect(Uglifier.compile(code, :mangle => { :toplevel => false })).to include("bar(")
53
- expect(Uglifier.compile(code, :mangle => { :toplevel => true })).not_to include("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)")
54
89
  end
55
90
  end
56
91
 
57
92
  describe "comment preservation" do
58
93
  let(:source) do
59
- <<-EOS
94
+ <<-JS
60
95
  /* @preserve Copyright Notice */
61
96
  /* (c) 2011 */
62
97
  // INCLUDED
@@ -65,8 +100,8 @@ describe "Uglifier" do
65
100
  /* Another Copyright */
66
101
  /*! Another Bang */
67
102
  // A comment!
68
- function add(a, b) { return a + b; }
69
- EOS
103
+ function add(a, b) { return a + b; }
104
+ JS
70
105
  end
71
106
 
72
107
  it "handles copyright option" do
@@ -118,8 +153,8 @@ describe "Uglifier" do
118
153
  subject { Uglifier.compile(source, :comments => :none) }
119
154
 
120
155
  it "omits all comments" do
121
- expect(subject).not_to match %r{//}
122
- expect(subject).not_to match(/\/\*/)
156
+ expect(subject).not_to match(%r{//})
157
+ expect(subject).not_to match(%r{/\*})
123
158
  end
124
159
  end
125
160
 
@@ -155,10 +190,22 @@ describe "Uglifier" do
155
190
  expect(minified).to match(/var \w,\w/)
156
191
  end
157
192
 
158
- it "forwards screw_ie8 option to UglifyJS" do
159
- code = "function something() { return g['switch']; }"
160
- expect(Uglifier.compile(code, :mangle => false, :screw_ie8 => true)).to match(/g\.switch/)
161
- expect(Uglifier.compile(code, :compress => false, :screw_ie8 => true)).to match(/g\.switch/)
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
162
209
  end
163
210
 
164
211
  it "can be configured to output only ASCII" do
@@ -212,13 +259,33 @@ describe "Uglifier" do
212
259
  expect(compiled).not_to include("console")
213
260
  end
214
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
+
215
282
  it "processes @ngInject annotations" do
216
- code = <<-EOF
283
+ code = <<-JS
217
284
  /**
218
285
  * @ngInject
219
286
  */
220
287
  var f = function(foo, bar) { return foo + bar};
221
- EOF
288
+ JS
222
289
  with_angular = Uglifier.compile(code, :compress => { :angular => true })
223
290
  without_angular = Uglifier.compile(code, :compress => { :angular => false })
224
291
  expect(with_angular).to include("f.$inject")
@@ -226,10 +293,10 @@ describe "Uglifier" do
226
293
  end
227
294
 
228
295
  it "keeps unused function arguments when keep_fargs option is set" do
229
- code = <<-EOF
296
+ code = <<-JS
230
297
  function plus(a, b, c) { return a + b};
231
298
  plus(1, 2);
232
- EOF
299
+ JS
233
300
 
234
301
  options = lambda do |keep_fargs|
235
302
  {
@@ -245,6 +312,16 @@ describe "Uglifier" do
245
312
  expect(Uglifier.compile(code, options.call(true))).to include("c)")
246
313
  end
247
314
 
315
+ it "keeps function names in output when 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_fargs = Uglifier.compile(code, :mangle => false, :compress => { :keep_fnames => true })
322
+ expect(keep_fargs).to include("plus")
323
+ end
324
+
248
325
  describe "Input Formats" do
249
326
  let(:code) { "function hello() { return 'hello world'; }" }
250
327