Bug 1090599 - Upgrade in-tree jsmin to release-2.0.11. r=gps

This updates to release-2.0.11 (sha1: 04374472ed18) from
https://bitbucket.org/dcs/jsmin/.
This commit is contained in:
Nick Alexander 2014-10-30 17:02:33 -07:00
parent 536f406826
commit 0da1c82db7
2 changed files with 152 additions and 7 deletions

View File

@ -37,7 +37,7 @@ else:
__all__ = ['jsmin', 'JavascriptMinify']
__version__ = '2.0.3'
__version__ = '2.0.11'
def jsmin(js):
@ -72,7 +72,20 @@ class JavascriptMinify(object):
def minify(self, instream=None, outstream=None):
if instream and outstream:
self.ins, self.outs = instream, outstream
write = self.outs.write
self.is_return = False
self.return_buf = ''
def write(char):
# all of this is to support literal regular expressions.
# sigh
if char in 'return':
self.return_buf += char
self.is_return = self.return_buf == 'return'
self.outs.write(char)
if self.is_return:
self.return_buf = ''
read = self.ins.read
space_strings = "abcdefghijklmnopqrstuvwxyz"\
@ -82,6 +95,7 @@ class JavascriptMinify(object):
newlineend_strings = enders + space_strings
do_newline = False
do_space = False
escape_slash_count = 0
doing_single_comment = False
previous_before_comment = ''
doing_multi_comment = False
@ -90,13 +104,18 @@ class JavascriptMinify(object):
quote_buf = []
previous = read(1)
if previous == '\\':
escape_slash_count += 1
next1 = read(1)
if previous == '/':
if next1 == '/':
doing_single_comment = True
elif next1 == '*':
doing_multi_comment = True
previous = next1
next1 = read(1)
else:
in_re = True # literal regex at start of script
write(previous)
elif not previous:
return
@ -111,16 +130,20 @@ class JavascriptMinify(object):
return
while 1:
next2 = read(1)
next2 = read(1)
if not next2:
last = next1.strip()
if not (doing_single_comment or doing_multi_comment)\
and last not in ('', '/'):
if in_quote:
write(''.join(quote_buf))
write(last)
break
if doing_multi_comment:
if next1 == '*' and next2 == '/':
doing_multi_comment = False
if previous_before_comment and previous_before_comment in space_strings:
do_space = True
next2 = read(1)
elif doing_single_comment:
if next1 in '\r\n':
@ -164,9 +187,17 @@ class JavascriptMinify(object):
or previous_non_space > '~') \
and (next2 in space_strings or next2 > '~'):
do_space = True
elif previous_non_space in '-+' and next2 == previous_non_space:
# protect against + ++ or - -- sequences
do_space = True
elif self.is_return and next2 == '/':
# returning a regex...
write(' ')
elif next1 == '/':
if do_space:
write(' ')
if in_re:
if previous != '\\':
if previous != '\\' or (not escape_slash_count % 2) or next2 in 'gimy':
in_re = False
write('/')
elif next2 == '/':
@ -174,8 +205,12 @@ class JavascriptMinify(object):
previous_before_comment = previous_non_space
elif next2 == '*':
doing_multi_comment = True
previous_before_comment = previous_non_space
previous = next1
next1 = next2
next2 = read(1)
else:
in_re = previous_non_space in '(,=:[?!&|'
in_re = previous_non_space in '(,=:[?!&|;' or self.is_return # literal regular expression
write('/')
else:
if do_space:
@ -184,12 +219,19 @@ class JavascriptMinify(object):
if do_newline:
write('\n')
do_newline = False
write(next1)
if not in_re and next1 in "'\"":
in_quote = next1
quote_buf = []
previous = next1
next1 = next2
if previous >= '!':
previous_non_space = previous
if previous == '\\':
escape_slash_count += 1
else:
escape_slash_count = 0

View File

@ -94,10 +94,37 @@ another thing;"""
"""
expected = r"""function foo(){alert('crud');}"""
self.assertMinified(js, expected)
def testBlockCommentStartingWithSlash(self):
self.assertMinified('A; /*/ comment */ B', 'A;B')
def testBlockCommentEndingWithSlash(self):
self.assertMinified('A; /* comment /*/ B', 'A;B')
def testLeadingBlockCommentStartingWithSlash(self):
self.assertMinified('/*/ comment */ A', 'A')
def testLeadingBlockCommentEndingWithSlash(self):
self.assertMinified('/* comment /*/ A', 'A')
def testEmptyBlockComment(self):
self.assertMinified('/**/ A', 'A')
def testBlockCommentMultipleOpen(self):
self.assertMinified('/* A /* B */ C', 'C')
def testJustAComment(self):
self.assertMinified(' // a comment', '')
def test_issue_10(self):
js = '''
files = [{name: value.replace(/^.*\\\\/, '')}];
// comment
A
'''
expected = '''files=[{name:value.replace(/^.*\\\\/,'')}]; A'''
self.assertMinified(js, expected)
def testRe(self):
js = r'''
var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
@ -153,6 +180,20 @@ Element.cleanWhitespace(element);"""
expected = r"""inspect:function(useDoubleQuotes){var escapedString=this.gsub(/[\x00-\x1f\\]/,function(match){var character=String.specialChar[match[0]];return character?character:'\\u00'+match[0].charCodeAt().toPaddedString(2,16);});if(useDoubleQuotes)return'"'+escapedString.replace(/"/g,'\\"')+'"';return"'"+escapedString.replace(/'/g,'\\\'')+"'";},toJSON:function(){return this.inspect(true);},unfilterJSON:function(filter){return this.sub(filter||Prototype.JSONFilter,'#{1}');},"""
self.assertMinified(js, expected)
def testLiteralRe(self):
js = r"""
myString.replace(/\\/g, '/');
console.log("hi");
"""
expected = r"""myString.replace(/\\/g,'/');console.log("hi");"""
self.assertMinified(js, expected)
js = r''' return /^data:image\//i.test(url) ||
/^(https?|ftp|file|about|chrome|resource):/.test(url);
'''
expected = r'''return /^data:image\//i.test(url)||/^(https?|ftp|file|about|chrome|resource):/.test(url);'''
self.assertMinified(js, expected)
def testNoBracesWithComment(self):
js = r"""
onSuccess: function(transport) {
@ -247,6 +288,68 @@ var foo = "hey";
self.assertMinified('x.replace(/\//, "_")// slash to underscore',
'x.replace(/\//,"_")')
def testSlashesNearComments(self):
original = '''
{ a: n / 2, }
// comment
'''
expected = '''{a:n/2,}'''
self.assertMinified(original, expected)
def testReturn(self):
original = '''
return foo;//comment
return bar;'''
expected = 'return foo; return bar;'
self.assertMinified(original, expected)
def test_space_plus(self):
original = '"s" + ++e + "s"'
expected = '"s"+ ++e+"s"'
self.assertMinified(original, expected)
def test_no_final_newline(self):
original = '"s"'
expected = '"s"'
self.assertMinified(original, expected)
def test_space_with_regex_repeats(self):
original = '/(NaN| {2}|^$)/.test(a)&&(a="M 0 0");'
self.assertMinified(original, original) # there should be nothing jsmin can do here
def test_space_with_regex_repeats_not_at_start(self):
original = 'aaa;/(NaN| {2}|^$)/.test(a)&&(a="M 0 0");'
self.assertMinified(original, original) # there should be nothing jsmin can do here
def test_space_in_regex(self):
original = '/a (a)/.test("a")'
self.assertMinified(original, original)
def test_angular_1(self):
original = '''var /** holds major version number for IE or NaN for real browsers */
msie,
jqLite, // delay binding since jQuery could be loaded after us.'''
minified = jsmin.jsmin(original)
self.assertTrue('var msie' in minified)
def test_angular_2(self):
original = 'var/* comment */msie;'
expected = 'var msie;'
self.assertMinified(original, expected)
def test_angular_3(self):
original = 'var /* comment */msie;'
expected = 'var msie;'
self.assertMinified(original, expected)
def test_angular_4(self):
original = 'var /* comment */ msie;'
expected = 'var msie;'
self.assertMinified(original, expected)
def test_angular_4(self):
original = 'a/b'
self.assertMinified(original, original)
if __name__ == '__main__':
unittest.main()