3 class JavaScriptMinifierTest
extends MediaWikiTestCase
{
5 function provideCases() {
8 array( "\r\t\f \v\n\r", "" ),
9 array( "/* Foo *\n*bar\n*/", "" ),
14 array( "' Foo \\' bar \\\n baz \\' quox ' .length", "' Foo \\' bar \\\n baz \\' quox '.length" ),
15 array( "\" Foo \\\" bar \\\n baz \\\" quox \" .length", "\" Foo \\\" bar \\\n baz \\\" quox \".length" ),
16 array( "// Foo b/ar baz", "" ),
17 array( "/ Foo \\/ bar [ / \\] / ] baz / .length", "/ Foo \\/ bar [ / \\] / ] baz /.length" ),
19 array( "<!-- Foo bar", "" ),
20 array( "<!-- Foo --> bar", "" ),
21 array( "--> Foo", "" ),
22 array( "x --> y", "x-->y" ),
23 // Semicolon insertion
24 array( "(function(){return\nx;})", "(function(){return\nx;})" ),
25 array( "throw\nx;", "throw\nx;" ),
26 array( "while(p){continue\nx;}", "while(p){continue\nx;}" ),
27 array( "while(p){break\nx;}", "while(p){break\nx;}" ),
28 array( "var\nx;", "var x;" ),
29 array( "x\ny;", "x\ny;" ),
30 array( "x\n++y;", "x\n++y;" ),
31 array( "x\n!y;", "x\n!y;" ),
32 array( "x\n{y}", "x\n{y}" ),
33 array( "x\n+y;", "x+y;" ),
34 array( "x\n(y);", "x(y);" ),
35 array( "5.\nx;", "5.\nx;" ),
36 array( "0xFF.\nx;", "0xFF.x;" ),
37 array( "5.3.\nx;", "5.3.x;" ),
39 array( "x in y", "x in y" ),
40 array( "/x/g in y", "/x/g in y" ),
41 array( "x in 30", "x in 30" ),
42 array( "x + ++ y", "x+ ++y" ),
43 array( "x / /y/.exec(z)", "x/ /y/.exec(z)" ),
45 array( "/ x/g", "/ x/g" ),
46 array( "(function(){return/ x/g})", "(function(){return/ x/g})" ),
47 array( "+/ x/g", "+/ x/g" ),
48 array( "++/ x/g", "++/ x/g" ),
49 array( "x/ x/g", "x/x/g" ),
50 array( "(/ x/g)", "(/ x/g)" ),
51 array( "if(/ x/g);", "if(/ x/g);" ),
52 array( "(x/ x/g)", "(x/x/g)" ),
53 array( "([/ x/g])", "([/ x/g])" ),
54 array( "+x/ x/g", "+x/x/g" ),
55 array( "{}/ x/g", "{}/ x/g" ),
56 array( "+{}/ x/g", "+{}/x/g" ),
57 array( "(x)/ x/g", "(x)/x/g" ),
58 array( "if(x)/ x/g", "if(x)/ x/g" ),
59 array( "for(x;x;{}/ x/g);", "for(x;x;{}/x/g);" ),
60 array( "x;x;{}/ x/g", "x;x;{}/ x/g" ),
61 array( "x:{}/ x/g", "x:{}/ x/g" ),
62 array( "switch(x){case y?z:{}/ x/g:{}/ x/g;}", "switch(x){case y?z:{}/x/g:{}/ x/g;}" ),
63 array( "function x(){}/ x/g", "function x(){}/ x/g" ),
64 array( "+function x(){}/ x/g", "+function x(){}/x/g" ),
66 // Tests for things that broke in the past
67 // Multiline quoted string
68 array( "var foo=\"\\\nblah\\\n\";", "var foo=\"\\\nblah\\\n\";" ),
69 // Multiline quoted string followed by string with spaces
70 array( "var foo=\"\\\nblah\\\n\";\nvar baz = \" foo \";\n", "var foo=\"\\\nblah\\\n\";var baz=\" foo \";" ),
71 // URL in quoted string ( // is not a comment)
72 array( "aNode.setAttribute('href','http://foo.bar.org/baz');", "aNode.setAttribute('href','http://foo.bar.org/baz');" ),
73 // URL in quoted string after multiline quoted string
74 array( "var foo=\"\\\nblah\\\n\";\naNode.setAttribute('href','http://foo.bar.org/baz');", "var foo=\"\\\nblah\\\n\";aNode.setAttribute('href','http://foo.bar.org/baz');" ),
75 // Division vs. regex nastiness
76 array( "alert( (10+10) / '/'.charCodeAt( 0 ) + '//' );", "alert((10+10)/'/'.charCodeAt(0)+'//');" ),
77 array( "if(1)/a /g.exec('Pa ss');", "if(1)/a /g.exec('Pa ss');" ),
79 // newline insertion after 1000 chars: break after the "++", not before
80 array( str_repeat( ';', 996 ) . "if(x++);", str_repeat( ';', 996 ) . "if(x++\n);" ),
85 * @dataProvider provideCases
87 function testJavaScriptMinifierOutput( $code, $expectedOutput ) {
88 $minified = JavaScriptMinifier
::minify( $code );
90 // JSMin+'s parser will throw an exception if output is not valid JS.
91 // suppression of warnings needed for stupid crap
93 $parser = new JSParser();
95 $parser->parse( $minified, 'minify-test.js', 1 );
97 $this->assertEquals( $expectedOutput, $minified, "Minified output should be in the form expected." );