uglifier 0.3.0 → 0.4.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,12 +3,12 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
- gem "therubyracer", ">= 0.8.0"
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.3.0"
11
+ gem "rspec", "~> 2.5.0"
12
12
  gem "bundler", "~> 1.0.0"
13
13
  gem "jeweler", "~> 1.5.0"
14
14
  gem "rcov", ">= 0"
data/Rakefile CHANGED
@@ -17,15 +17,9 @@ Jeweler::Tasks.new do |gem|
17
17
  gem.email = "lautis@gmail.com"
18
18
  gem.homepage = "http://github.com/lautis/uglifier"
19
19
  gem.authors = ["Ville Lautanala"]
20
- # Include your dependencies below. Runtime dependencies are required when using your gem,
21
- # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
22
- # spec.add_runtime_dependency 'jabber4r', '> 0.1'
23
- # spec.add_development_dependency 'rspec', '> 1.2.3'
24
- gem.add_development_dependency "therubyracer", ">=0.7.5"
25
- gem.add_development_dependency "rspec", "~> 2.0.0"
26
- gem.add_development_dependency "bundler", "~> 1.0.0"
27
- gem.add_development_dependency "jeweler", "~> 1.5.0.pre5"
28
- gem.add_development_dependency "rcov", ">= 0"
20
+
21
+ # Dependencies defined in Gemfile
22
+
29
23
  gem.files.include 'vendor/uglifyjs/lib/*'
30
24
  end
31
25
  Jeweler::RubygemsDotOrgTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
data/lib/uglifier.rb CHANGED
@@ -10,7 +10,6 @@ class Uglifier
10
10
  :squeeze => true, # Squeeze code resulting in smaller, but less-readable code
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
- :extra => false, # Additional and potentially unsafe optimizations
14
13
  :unsafe => false, # Optimizations known to be unsafe in some situations
15
14
  :copyright => true, # Show copyright message
16
15
  :beautify => false, # Ouput indented code
@@ -59,22 +58,14 @@ class Uglifier
59
58
  end
60
59
 
61
60
  def copyright(source)
62
- comments = []
63
-
64
61
  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"
62
+ tokens.call.comments_before.inject("") do |copyright, comment|
63
+ copyright + if comment["type"] == "comment1"
64
+ "//" + comment["value"] + "\n"
71
65
  else
72
- "/*#{comment["value"]}*/\n"
66
+ "/*" + comment["value"] + "*/\n"
73
67
  end
74
- prev = comment["type"]
75
- comment = tokens.call
76
68
  end
77
- comments.join
78
69
  end
79
70
 
80
71
  def generate_code(ast)
@@ -96,7 +87,7 @@ class Uglifier
96
87
  @node["ast_squeeze"].call(ast, {
97
88
  "make_seqs" => @options[:seqs],
98
89
  "dead_code" => @options[:dead_code],
99
- "extra" => @options[:extra]
90
+ "keep_comps" => !@options[:unsafe]
100
91
  })
101
92
  end
102
93
 
data/lib/uglifier/cli.rb CHANGED
@@ -27,10 +27,6 @@ class Uglifier
27
27
  options[:dead_code] = d
28
28
  end
29
29
 
30
- opts.on("-x", "--extra-optimizations", "Additional and potentially unsafe optimizations") do |x|
31
- options[:extra] = x
32
- end
33
-
34
30
  opts.on("-u", "--unsafe-optimizations", "Optimizations known to be unsafe in some situations") do |d|
35
31
  options[:unsafe] = d
36
32
  end
@@ -31,7 +31,7 @@ describe "Uglifier" do
31
31
  @source = <<-EOS
32
32
  /* Copyright Notice */
33
33
  /* (c) 2011 */
34
- // REMOVED
34
+ // INCLUDED
35
35
  function identity(p) { return p; }
36
36
  EOS
37
37
  @minified = Uglifier.compile(@source, :copyright => true)
@@ -45,12 +45,12 @@ describe "Uglifier" do
45
45
  @minified.should match /\(c\) 2011/
46
46
  end
47
47
 
48
- it "doesn't include different comment types" do
49
- @minified.should_not match /REMOVED/
48
+ it "does include different comment types" do
49
+ @minified.should match /INCLUDED/
50
50
  end
51
51
 
52
52
  it "puts comments on own lines" do
53
- @minified.split("\n").should have(3).items
53
+ @minified.split("\n").should have(4).items
54
54
  end
55
55
 
56
56
  it "omits copyright notification if copyright parameter is set to false" do
data/uglifier.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{uglifier}
8
- s.version = "0.3.0"
8
+ s.version = "0.4.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{2011-01-06}
12
+ s.date = %q{2011-02-26}
13
13
  s.default_executable = %q{uglify}
14
14
  s.email = %q{lautis@gmail.com}
15
15
  s.executables = ["uglify"]
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
39
39
  ]
40
40
  s.homepage = %q{http://github.com/lautis/uglifier}
41
41
  s.require_paths = ["lib"]
42
- s.rubygems_version = %q{1.3.7}
42
+ s.rubygems_version = %q{1.5.0}
43
43
  s.summary = %q{Ruby wrapper for UglifyJS JavaScript compressor}
44
44
  s.test_files = [
45
45
  "spec/spec_helper.rb",
@@ -47,43 +47,27 @@ Gem::Specification.new do |s|
47
47
  ]
48
48
 
49
49
  if s.respond_to? :specification_version then
50
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
51
50
  s.specification_version = 3
52
51
 
53
52
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
- s.add_runtime_dependency(%q<therubyracer>, [">= 0.8.0"])
55
- s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
53
+ s.add_runtime_dependency(%q<therubyracer>, ["~> 0.8.0"])
54
+ s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
56
55
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
57
56
  s.add_development_dependency(%q<jeweler>, ["~> 1.5.0"])
58
57
  s.add_development_dependency(%q<rcov>, [">= 0"])
59
- s.add_development_dependency(%q<therubyracer>, [">= 0.7.5"])
60
- s.add_development_dependency(%q<rspec>, ["~> 2.0.0"])
61
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
62
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
63
- s.add_development_dependency(%q<rcov>, [">= 0"])
64
58
  else
65
- s.add_dependency(%q<therubyracer>, [">= 0.8.0"])
66
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
59
+ s.add_dependency(%q<therubyracer>, ["~> 0.8.0"])
60
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
67
61
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
68
62
  s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
69
63
  s.add_dependency(%q<rcov>, [">= 0"])
70
- s.add_dependency(%q<therubyracer>, [">= 0.7.5"])
71
- s.add_dependency(%q<rspec>, ["~> 2.0.0"])
72
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
73
- s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
74
- s.add_dependency(%q<rcov>, [">= 0"])
75
64
  end
76
65
  else
77
- s.add_dependency(%q<therubyracer>, [">= 0.8.0"])
78
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
66
+ s.add_dependency(%q<therubyracer>, ["~> 0.8.0"])
67
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
79
68
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
80
69
  s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
81
70
  s.add_dependency(%q<rcov>, [">= 0"])
82
- s.add_dependency(%q<therubyracer>, [">= 0.7.5"])
83
- s.add_dependency(%q<rspec>, ["~> 2.0.0"])
84
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
85
- s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
86
- s.add_dependency(%q<rcov>, [">= 0"])
87
71
  end
88
72
  end
89
73
 
@@ -182,7 +182,6 @@ var OPERATORS = array_to_hash([
182
182
  ">>=",
183
183
  "<<=",
184
184
  ">>>=",
185
- "~=",
186
185
  "%=",
187
186
  "|=",
188
187
  "^=",
@@ -191,7 +190,7 @@ var OPERATORS = array_to_hash([
191
190
  "||"
192
191
  ]);
193
192
 
194
- var WHITESPACE_CHARS = array_to_hash(characters(" \n\r\t"));
193
+ var WHITESPACE_CHARS = array_to_hash(characters(" \n\r\t\u200b"));
195
194
 
196
195
  var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:"));
197
196
 
@@ -201,20 +200,47 @@ var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy"));
201
200
 
202
201
  /* -----[ Tokenizer ]----- */
203
202
 
204
- function is_alphanumeric_char(ch) {
205
- ch = ch.charCodeAt(0);
206
- return (ch >= 48 && ch <= 57) ||
207
- (ch >= 65 && ch <= 90) ||
208
- (ch >= 97 && ch <= 122);
203
+ // regexps adapted from http://xregexp.com/plugins/#unicode
204
+ var UNICODE = {
205
+ letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),
206
+ non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"),
207
+ space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"),
208
+ connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
209
209
  };
210
210
 
211
- function is_identifier_char(ch) {
212
- return is_alphanumeric_char(ch) || ch == "$" || ch == "_";
211
+ function is_letter(ch) {
212
+ return UNICODE.letter.test(ch);
213
213
  };
214
214
 
215
215
  function is_digit(ch) {
216
216
  ch = ch.charCodeAt(0);
217
- return ch >= 48 && ch <= 57;
217
+ return ch >= 48 && ch <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9
218
+ };
219
+
220
+ function is_alphanumeric_char(ch) {
221
+ return is_digit(ch) || is_letter(ch);
222
+ };
223
+
224
+ function is_unicode_combining_mark(ch) {
225
+ return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
226
+ };
227
+
228
+ function is_unicode_connector_punctuation(ch) {
229
+ return UNICODE.connector_punctuation.test(ch);
230
+ };
231
+
232
+ function is_identifier_start(ch) {
233
+ return ch == "$" || ch == "_" || is_letter(ch);
234
+ };
235
+
236
+ function is_identifier_char(ch) {
237
+ return is_identifier_start(ch)
238
+ || is_unicode_combining_mark(ch)
239
+ || is_digit(ch)
240
+ || is_unicode_connector_punctuation(ch)
241
+ || ch == "\u200c" // zero-width non-joiner <ZWNJ>
242
+ || ch == "\u200d" // zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
243
+ ;
218
244
  };
219
245
 
220
246
  function parse_js_number(num) {
@@ -253,18 +279,19 @@ function is_token(token, type, val) {
253
279
 
254
280
  var EX_EOF = {};
255
281
 
256
- function tokenizer($TEXT, skip_comments) {
282
+ function tokenizer($TEXT) {
257
283
 
258
284
  var S = {
259
- text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''),
260
- pos : 0,
261
- tokpos : 0,
262
- line : 0,
263
- tokline : 0,
264
- col : 0,
265
- tokcol : 0,
266
- newline_before : false,
267
- regex_allowed : false
285
+ text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''),
286
+ pos : 0,
287
+ tokpos : 0,
288
+ line : 0,
289
+ tokline : 0,
290
+ col : 0,
291
+ tokcol : 0,
292
+ newline_before : false,
293
+ regex_allowed : false,
294
+ comments_before : []
268
295
  };
269
296
 
270
297
  function peek() { return S.text.charAt(S.pos); };
@@ -299,7 +326,7 @@ function tokenizer($TEXT, skip_comments) {
299
326
  S.tokpos = S.pos;
300
327
  };
301
328
 
302
- function token(type, value) {
329
+ function token(type, value, is_comment) {
303
330
  S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) ||
304
331
  (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||
305
332
  (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value)));
@@ -311,6 +338,10 @@ function tokenizer($TEXT, skip_comments) {
311
338
  pos : S.tokpos,
312
339
  nlb : S.newline_before
313
340
  };
341
+ if (!is_comment) {
342
+ ret.comments_before = S.comments_before;
343
+ S.comments_before = [];
344
+ }
314
345
  S.newline_before = false;
315
346
  return ret;
316
347
  };
@@ -334,7 +365,7 @@ function tokenizer($TEXT, skip_comments) {
334
365
  };
335
366
 
336
367
  function read_num(prefix) {
337
- var has_e = false, after_e = false, has_x = false;
368
+ var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
338
369
  var num = read_while(function(ch, i){
339
370
  if (ch == "x" || ch == "X") {
340
371
  if (has_x) return false;
@@ -350,7 +381,12 @@ function tokenizer($TEXT, skip_comments) {
350
381
  }
351
382
  if (ch == "+") return after_e;
352
383
  after_e = false;
353
- return is_alphanumeric_char(ch) || ch == ".";
384
+ if (ch == ".") {
385
+ if (!has_dot)
386
+ return has_dot = true;
387
+ return false;
388
+ }
389
+ return is_alphanumeric_char(ch);
354
390
  });
355
391
  if (prefix)
356
392
  num = prefix + num;
@@ -412,7 +448,7 @@ function tokenizer($TEXT, skip_comments) {
412
448
  ret = S.text.substring(S.pos, i);
413
449
  S.pos = i;
414
450
  }
415
- return token("comment1", ret);
451
+ return token("comment1", ret, true);
416
452
  };
417
453
 
418
454
  function read_multiline_comment() {
@@ -420,14 +456,41 @@ function tokenizer($TEXT, skip_comments) {
420
456
  return with_eof_error("Unterminated multiline comment", function(){
421
457
  var i = find("*/", true),
422
458
  text = S.text.substring(S.pos, i),
423
- tok = token("comment2", text);
459
+ tok = token("comment2", text, true);
424
460
  S.pos = i + 2;
425
461
  S.line += text.split("\n").length - 1;
426
462
  S.newline_before = text.indexOf("\n") >= 0;
463
+
464
+ // https://github.com/mishoo/UglifyJS/issues/#issue/100
465
+ if (/^@cc_on/i.test(text)) {
466
+ warn("WARNING: at line " + S.line);
467
+ warn("*** Found \"conditional comment\": " + text);
468
+ warn("*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer.");
469
+ }
470
+
427
471
  return tok;
428
472
  });
429
473
  };
430
474
 
475
+ function read_name() {
476
+ var backslash = false, name = "", ch;
477
+ while ((ch = peek()) != null) {
478
+ if (!backslash) {
479
+ if (ch == "\\") backslash = true, next();
480
+ else if (is_identifier_char(ch)) name += next();
481
+ else break;
482
+ }
483
+ else {
484
+ if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
485
+ ch = read_escaped_char();
486
+ if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
487
+ name += ch;
488
+ backslash = false;
489
+ }
490
+ }
491
+ return name;
492
+ };
493
+
431
494
  function read_regexp() {
432
495
  return with_eof_error("Unterminated regular expression", function(){
433
496
  var prev_backslash = false, regexp = "", ch, in_class = false;
@@ -447,15 +510,14 @@ function tokenizer($TEXT, skip_comments) {
447
510
  } else {
448
511
  regexp += ch;
449
512
  }
450
- var mods = read_while(function(ch){
451
- return HOP(REGEXP_MODIFIERS, ch);
452
- });
513
+ var mods = read_name();
453
514
  return token("regexp", [ regexp, mods ]);
454
515
  });
455
516
  };
456
517
 
457
518
  function read_operator(prefix) {
458
519
  function grow(op) {
520
+ if (!peek()) return op;
459
521
  var bigger = op + peek();
460
522
  if (HOP(OPERATORS, bigger)) {
461
523
  next();
@@ -467,19 +529,18 @@ function tokenizer($TEXT, skip_comments) {
467
529
  return token("operator", grow(prefix || next()));
468
530
  };
469
531
 
470
- var handle_slash = skip_comments ? function() {
532
+ function handle_slash() {
471
533
  next();
472
534
  var regex_allowed = S.regex_allowed;
473
535
  switch (peek()) {
474
- case "/": read_line_comment(); S.regex_allowed = regex_allowed; return next_token();
475
- case "*": read_multiline_comment(); S.regex_allowed = regex_allowed; return next_token();
476
- }
477
- return S.regex_allowed ? read_regexp() : read_operator("/");
478
- } : function() {
479
- next();
480
- switch (peek()) {
481
- case "/": return read_line_comment();
482
- case "*": return read_multiline_comment();
536
+ case "/":
537
+ S.comments_before.push(read_line_comment());
538
+ S.regex_allowed = regex_allowed;
539
+ return next_token();
540
+ case "*":
541
+ S.comments_before.push(read_multiline_comment());
542
+ S.regex_allowed = regex_allowed;
543
+ return next_token();
483
544
  }
484
545
  return S.regex_allowed ? read_regexp() : read_operator("/");
485
546
  };
@@ -492,7 +553,7 @@ function tokenizer($TEXT, skip_comments) {
492
553
  };
493
554
 
494
555
  function read_word() {
495
- var word = read_while(is_identifier_char);
556
+ var word = read_name();
496
557
  return !HOP(KEYWORDS, word)
497
558
  ? token("name", word)
498
559
  : HOP(OPERATORS, word)
@@ -524,7 +585,7 @@ function tokenizer($TEXT, skip_comments) {
524
585
  if (ch == ".") return handle_dot();
525
586
  if (ch == "/") return handle_slash();
526
587
  if (HOP(OPERATOR_CHARS, ch)) return read_operator();
527
- if (is_identifier_char(ch)) return read_word();
588
+ if (ch == "\\" || is_identifier_start(ch)) return read_word();
528
589
  parse_error("Unexpected character '" + ch + "'");
529
590
  };
530
591
 
@@ -560,7 +621,7 @@ var ASSIGNMENT = (function(a, ret, i){
560
621
  }
561
622
  return ret;
562
623
  })(
563
- ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "~=", "%=", "|=", "^=", "&="],
624
+ ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="],
564
625
  { "=": true },
565
626
  0
566
627
  );
@@ -603,16 +664,16 @@ function NodeWithToken(str, start, end) {
603
664
 
604
665
  NodeWithToken.prototype.toString = function() { return this.name; };
605
666
 
606
- function parse($TEXT, strict_mode, embed_tokens) {
667
+ function parse($TEXT, exigent_mode, embed_tokens) {
607
668
 
608
669
  var S = {
609
- input: tokenizer($TEXT, true),
610
- token: null,
611
- prev: null,
612
- peeked: null,
613
- in_function: 0,
614
- in_loop: 0,
615
- labels: []
670
+ input : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT,
671
+ token : null,
672
+ prev : null,
673
+ peeked : null,
674
+ in_function : 0,
675
+ in_loop : 0,
676
+ labels : []
616
677
  };
617
678
 
618
679
  S.token = next();
@@ -666,7 +727,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
666
727
  function expect(punc) { return expect_token("punc", punc); };
667
728
 
668
729
  function can_insert_semicolon() {
669
- return !strict_mode && (
730
+ return !exigent_mode && (
670
731
  S.token.nlb || is("eof") || is("punc", "}")
671
732
  );
672
733
  };
@@ -688,14 +749,14 @@ function parse($TEXT, strict_mode, embed_tokens) {
688
749
  };
689
750
 
690
751
  function add_tokens(str, start, end) {
691
- return new NodeWithToken(str, start, end);
752
+ return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);
692
753
  };
693
754
 
694
755
  var statement = embed_tokens ? function() {
695
756
  var start = S.token;
696
- var stmt = $statement();
697
- stmt[0] = add_tokens(stmt[0], start, prev());
698
- return stmt;
757
+ var ast = $statement.apply(this, arguments);
758
+ ast[0] = add_tokens(ast[0], start, prev());
759
+ return ast;
699
760
  } : $statement;
700
761
 
701
762
  function $statement() {
@@ -797,7 +858,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
797
858
  function labeled_statement(label) {
798
859
  S.labels.push(label);
799
860
  var start = S.token, stat = statement();
800
- if (strict_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
861
+ if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
801
862
  unexpected(start);
802
863
  S.labels.pop();
803
864
  return as("label", label, stat);
@@ -822,29 +883,42 @@ function parse($TEXT, strict_mode, embed_tokens) {
822
883
 
823
884
  function for_() {
824
885
  expect("(");
825
- var has_var = is("keyword", "var");
826
- if (has_var)
827
- next();
828
- if (is("name") && is_token(peek(), "operator", "in")) {
829
- // for (i in foo)
830
- var name = S.token.value;
831
- next(); next();
832
- var obj = expression();
833
- expect(")");
834
- return as("for-in", has_var, name, obj, in_loop(statement));
835
- } else {
836
- // classic for
837
- var init = is("punc", ";") ? null : has_var ? var_() : expression();
838
- expect(";");
839
- var test = is("punc", ";") ? null : expression();
840
- expect(";");
841
- var step = is("punc", ")") ? null : expression();
842
- expect(")");
843
- return as("for", init, test, step, in_loop(statement));
886
+ var init = null;
887
+ if (!is("punc", ";")) {
888
+ init = is("keyword", "var")
889
+ ? (next(), var_(true))
890
+ : expression(true, true);
891
+ if (is("operator", "in"))
892
+ return for_in(init);
844
893
  }
894
+ return regular_for(init);
845
895
  };
846
896
 
847
- function function_(in_statement) {
897
+ function regular_for(init) {
898
+ expect(";");
899
+ var test = is("punc", ";") ? null : expression();
900
+ expect(";");
901
+ var step = is("punc", ")") ? null : expression();
902
+ expect(")");
903
+ return as("for", init, test, step, in_loop(statement));
904
+ };
905
+
906
+ function for_in(init) {
907
+ var lhs = init[0] == "var" ? as("name", init[1][0]) : init;
908
+ next();
909
+ var obj = expression();
910
+ expect(")");
911
+ return as("for-in", init, lhs, obj, in_loop(statement));
912
+ };
913
+
914
+ var function_ = embed_tokens ? function() {
915
+ var start = prev();
916
+ var ast = $function_.apply(this, arguments);
917
+ ast[0] = add_tokens(ast[0], start, prev());
918
+ return ast;
919
+ } : $function_;
920
+
921
+ function $function_(in_statement) {
848
922
  var name = is("name") ? prog1(S.token.value, next) : null;
849
923
  if (in_statement && !name)
850
924
  unexpected();
@@ -941,7 +1015,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
941
1015
  return as("try", body, bcatch, bfinally);
942
1016
  };
943
1017
 
944
- function vardefs() {
1018
+ function vardefs(no_in) {
945
1019
  var a = [];
946
1020
  for (;;) {
947
1021
  if (!is("name"))
@@ -950,7 +1024,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
950
1024
  next();
951
1025
  if (is("operator", "=")) {
952
1026
  next();
953
- a.push([ name, expression(false) ]);
1027
+ a.push([ name, expression(false, no_in) ]);
954
1028
  } else {
955
1029
  a.push([ name ]);
956
1030
  }
@@ -961,8 +1035,8 @@ function parse($TEXT, strict_mode, embed_tokens) {
961
1035
  return a;
962
1036
  };
963
1037
 
964
- function var_() {
965
- return as("var", vardefs());
1038
+ function var_(no_in) {
1039
+ return as("var", vardefs(no_in));
966
1040
  };
967
1041
 
968
1042
  function const_() {
@@ -1017,27 +1091,30 @@ function parse($TEXT, strict_mode, embed_tokens) {
1017
1091
  unexpected();
1018
1092
  };
1019
1093
 
1020
- function expr_list(closing, allow_trailing_comma) {
1094
+ function expr_list(closing, allow_trailing_comma, allow_empty) {
1021
1095
  var first = true, a = [];
1022
1096
  while (!is("punc", closing)) {
1023
1097
  if (first) first = false; else expect(",");
1024
- if (allow_trailing_comma && is("punc", closing))
1025
- break;
1026
- a.push(expression(false));
1098
+ if (allow_trailing_comma && is("punc", closing)) break;
1099
+ if (is("punc", ",") && allow_empty) {
1100
+ a.push([ "atom", "undefined" ]);
1101
+ } else {
1102
+ a.push(expression(false));
1103
+ }
1027
1104
  }
1028
1105
  next();
1029
1106
  return a;
1030
1107
  };
1031
1108
 
1032
1109
  function array_() {
1033
- return as("array", expr_list("]", !strict_mode));
1110
+ return as("array", expr_list("]", !exigent_mode, true));
1034
1111
  };
1035
1112
 
1036
1113
  function object_() {
1037
1114
  var first = true, a = [];
1038
1115
  while (!is("punc", "}")) {
1039
1116
  if (first) first = false; else expect(",");
1040
- if (!strict_mode && is("punc", "}"))
1117
+ if (!exigent_mode && is("punc", "}"))
1041
1118
  // allow trailing comma
1042
1119
  break;
1043
1120
  var type = S.token.type;
@@ -1100,61 +1177,65 @@ function parse($TEXT, strict_mode, embed_tokens) {
1100
1177
  return as(tag, op, expr);
1101
1178
  };
1102
1179
 
1103
- function expr_op(left, min_prec) {
1180
+ function expr_op(left, min_prec, no_in) {
1104
1181
  var op = is("operator") ? S.token.value : null;
1182
+ if (op && op == "in" && no_in) op = null;
1105
1183
  var prec = op != null ? PRECEDENCE[op] : null;
1106
1184
  if (prec != null && prec > min_prec) {
1107
1185
  next();
1108
- var right = expr_op(expr_atom(true), prec);
1109
- return expr_op(as("binary", op, left, right), min_prec);
1186
+ var right = expr_op(expr_atom(true), prec, no_in);
1187
+ return expr_op(as("binary", op, left, right), min_prec, no_in);
1110
1188
  }
1111
1189
  return left;
1112
1190
  };
1113
1191
 
1114
- function expr_ops() {
1115
- return expr_op(expr_atom(true), 0);
1192
+ function expr_ops(no_in) {
1193
+ return expr_op(expr_atom(true), 0, no_in);
1116
1194
  };
1117
1195
 
1118
- function maybe_conditional() {
1119
- var expr = expr_ops();
1196
+ function maybe_conditional(no_in) {
1197
+ var expr = expr_ops(no_in);
1120
1198
  if (is("operator", "?")) {
1121
1199
  next();
1122
1200
  var yes = expression(false);
1123
1201
  expect(":");
1124
- return as("conditional", expr, yes, expression(false));
1202
+ return as("conditional", expr, yes, expression(false, no_in));
1125
1203
  }
1126
1204
  return expr;
1127
1205
  };
1128
1206
 
1129
1207
  function is_assignable(expr) {
1208
+ if (!exigent_mode) return true;
1130
1209
  switch (expr[0]) {
1131
1210
  case "dot":
1132
1211
  case "sub":
1212
+ case "new":
1213
+ case "call":
1133
1214
  return true;
1134
1215
  case "name":
1135
1216
  return expr[1] != "this";
1136
1217
  }
1137
1218
  };
1138
1219
 
1139
- function maybe_assign() {
1140
- var left = maybe_conditional(), val = S.token.value;
1220
+ function maybe_assign(no_in) {
1221
+ var left = maybe_conditional(no_in), val = S.token.value;
1141
1222
  if (is("operator") && HOP(ASSIGNMENT, val)) {
1142
1223
  if (is_assignable(left)) {
1143
1224
  next();
1144
- return as("assign", ASSIGNMENT[val], left, maybe_assign());
1225
+ return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in));
1145
1226
  }
1146
1227
  croak("Invalid assignment");
1147
1228
  }
1148
1229
  return left;
1149
1230
  };
1150
1231
 
1151
- function expression(commas) {
1232
+ function expression(commas, no_in) {
1152
1233
  if (arguments.length == 0)
1153
1234
  commas = true;
1154
- var expr = maybe_assign();
1235
+ var expr = maybe_assign(no_in);
1155
1236
  if (commas && is("punc", ",")) {
1156
1237
  next();
1157
- return as("seq", expr, expression());
1238
+ return as("seq", expr, expression(true, no_in));
1158
1239
  }
1159
1240
  return expr;
1160
1241
  };
@@ -1217,6 +1298,8 @@ function HOP(obj, prop) {
1217
1298
  return Object.prototype.hasOwnProperty.call(obj, prop);
1218
1299
  };
1219
1300
 
1301
+ var warn = function() {};
1302
+
1220
1303
  /* -----[ Exports ]----- */
1221
1304
 
1222
1305
  exports.tokenizer = tokenizer;
@@ -1232,3 +1315,6 @@ exports.KEYWORDS = KEYWORDS;
1232
1315
  exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;
1233
1316
  exports.OPERATORS = OPERATORS;
1234
1317
  exports.is_alphanumeric_char = is_alphanumeric_char;
1318
+ exports.set_logger = function(logger) {
1319
+ warn = logger;
1320
+ };