MediaWiki
REL1_22
|
00001 <?php 00002 00003 class JavaScriptMinifierTest extends MediaWikiTestCase { 00004 00005 public static function provideCases() { 00006 return array( 00007 00008 // Basic whitespace and comments that should be stripped entirely 00009 array( "\r\t\f \v\n\r", "" ), 00010 array( "/* Foo *\n*bar\n*/", "" ), 00011 00017 array( "/**\n * Foo\n * {\n * 'bar' : {\n * //Multiple rules with configurable operators\n * 'baz' : false\n * }\n */", "" ), 00018 00023 array( "' Foo \\' bar \\\n baz \\' quox ' .length", "' Foo \\' bar \\\n baz \\' quox '.length" ), 00024 array( "\" Foo \\\" bar \\\n baz \\\" quox \" .length", "\" Foo \\\" bar \\\n baz \\\" quox \".length" ), 00025 array( "// Foo b/ar baz", "" ), 00026 array( "/ Foo \\/ bar [ / \\] / ] baz / .length", "/ Foo \\/ bar [ / \\] / ] baz /.length" ), 00027 00028 // HTML comments 00029 array( "<!-- Foo bar", "" ), 00030 array( "<!-- Foo --> bar", "" ), 00031 array( "--> Foo", "" ), 00032 array( "x --> y", "x-->y" ), 00033 00034 // Semicolon insertion 00035 array( "(function(){return\nx;})", "(function(){return\nx;})" ), 00036 array( "throw\nx;", "throw\nx;" ), 00037 array( "while(p){continue\nx;}", "while(p){continue\nx;}" ), 00038 array( "while(p){break\nx;}", "while(p){break\nx;}" ), 00039 array( "var\nx;", "var x;" ), 00040 array( "x\ny;", "x\ny;" ), 00041 array( "x\n++y;", "x\n++y;" ), 00042 array( "x\n!y;", "x\n!y;" ), 00043 array( "x\n{y}", "x\n{y}" ), 00044 array( "x\n+y;", "x+y;" ), 00045 array( "x\n(y);", "x(y);" ), 00046 array( "5.\nx;", "5.\nx;" ), 00047 array( "0xFF.\nx;", "0xFF.x;" ), 00048 array( "5.3.\nx;", "5.3.x;" ), 00049 00050 // Semicolon insertion between an expression having an inline 00051 // comment after it, and a statement on the next line (bug 27046). 00052 array( "var a = this //foo bar \n for ( b = 0; c < d; b++ ) {}", "var a=this\nfor(b=0;c<d;b++){}" ), 00053 00054 // Token separation 00055 array( "x in y", "x in y" ), 00056 array( "/x/g in y", "/x/g in y" ), 00057 array( "x in 30", "x in 30" ), 00058 array( "x + ++ y", "x+ ++y" ), 00059 array( "x ++ + y", "x++ +y" ), 00060 array( "x / /y/.exec(z)", "x/ /y/.exec(z)" ), 00061 00062 // State machine 00063 array( "/ x/g", "/ x/g" ), 00064 array( "(function(){return/ x/g})", "(function(){return/ x/g})" ), 00065 array( "+/ x/g", "+/ x/g" ), 00066 array( "++/ x/g", "++/ x/g" ), 00067 array( "x/ x/g", "x/x/g" ), 00068 array( "(/ x/g)", "(/ x/g)" ), 00069 array( "if(/ x/g);", "if(/ x/g);" ), 00070 array( "(x/ x/g)", "(x/x/g)" ), 00071 array( "([/ x/g])", "([/ x/g])" ), 00072 array( "+x/ x/g", "+x/x/g" ), 00073 array( "{}/ x/g", "{}/ x/g" ), 00074 array( "+{}/ x/g", "+{}/x/g" ), 00075 array( "(x)/ x/g", "(x)/x/g" ), 00076 array( "if(x)/ x/g", "if(x)/ x/g" ), 00077 array( "for(x;x;{}/ x/g);", "for(x;x;{}/x/g);" ), 00078 array( "x;x;{}/ x/g", "x;x;{}/ x/g" ), 00079 array( "x:{}/ x/g", "x:{}/ x/g" ), 00080 array( "switch(x){case y?z:{}/ x/g:{}/ x/g;}", "switch(x){case y?z:{}/x/g:{}/ x/g;}" ), 00081 array( "function x(){}/ x/g", "function x(){}/ x/g" ), 00082 array( "+function x(){}/ x/g", "+function x(){}/x/g" ), 00083 00084 // Multiline quoted string 00085 array( "var foo=\"\\\nblah\\\n\";", "var foo=\"\\\nblah\\\n\";" ), 00086 00087 // Multiline quoted string followed by string with spaces 00088 array( "var foo=\"\\\nblah\\\n\";\nvar baz = \" foo \";\n", "var foo=\"\\\nblah\\\n\";var baz=\" foo \";" ), 00089 00090 // URL in quoted string ( // is not a comment) 00091 array( "aNode.setAttribute('href','http://foo.bar.org/baz');", "aNode.setAttribute('href','http://foo.bar.org/baz');" ), 00092 00093 // URL in quoted string after multiline quoted string 00094 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');" ), 00095 00096 // Division vs. regex nastiness 00097 array( "alert( (10+10) / '/'.charCodeAt( 0 ) + '//' );", "alert((10+10)/'/'.charCodeAt(0)+'//');" ), 00098 array( "if(1)/a /g.exec('Pa ss');", "if(1)/a /g.exec('Pa ss');" ), 00099 00100 // newline insertion after 1000 chars: break after the "++", not before 00101 array( str_repeat( ';', 996 ) . "if(x++);", str_repeat( ';', 996 ) . "if(x++\n);" ), 00102 00103 // Unicode letter characters should pass through ok in identifiers (bug 31187) 00104 array( "var KaŝSkatolVal = {}", 'var KaŝSkatolVal={}' ), 00105 00106 // Per spec unicode char escape values should work in identifiers, 00107 // as long as it's a valid char. In future it might get normalized. 00108 array( "var Ka\\u015dSkatolVal = {}", 'var Ka\\u015dSkatolVal={}' ), 00109 00110 // Some structures that might look invalid at first sight 00111 array( "var a = 5.;", "var a=5.;" ), 00112 array( "5.0.toString();", "5.0.toString();" ), 00113 array( "5..toString();", "5..toString();" ), 00114 array( "5...toString();", false ), 00115 array( "5.\n.toString();", '5..toString();' ), 00116 ); 00117 } 00118 00122 public function testJavaScriptMinifierOutput( $code, $expectedOutput ) { 00123 $minified = JavaScriptMinifier::minify( $code ); 00124 00125 // JSMin+'s parser will throw an exception if output is not valid JS. 00126 // suppression of warnings needed for stupid crap 00127 wfSuppressWarnings(); 00128 $parser = new JSParser(); 00129 wfRestoreWarnings(); 00130 $parser->parse( $minified, 'minify-test.js', 1 ); 00131 00132 $this->assertEquals( $expectedOutput, $minified, "Minified output should be in the form expected." ); 00133 } 00134 00135 public static function provideBug32548() { 00136 return array( 00137 array( 00138 // This one gets interpreted all together by the prior code; 00139 // no break at the 'E' happens. 00140 '1.23456789E55', 00141 ), 00142 array( 00143 // This one breaks under the bad code; splits between 'E' and '+' 00144 '1.23456789E+5', 00145 ), 00146 array( 00147 // This one breaks under the bad code; splits between 'E' and '-' 00148 '1.23456789E-5', 00149 ), 00150 ); 00151 } 00152 00156 public function testBug32548Exponent( $num ) { 00157 // Long line breaking was being incorrectly done between the base and 00158 // exponent part of a number, causing a syntax error. The line should 00159 // instead break at the start of the number. 00160 $prefix = 'var longVarName' . str_repeat( '_', 973 ) . '='; 00161 $suffix = ',shortVarName=0;'; 00162 00163 $input = $prefix . $num . $suffix; 00164 $expected = $prefix . "\n" . $num . $suffix; 00165 00166 $minified = JavaScriptMinifier::minify( $input ); 00167 00168 $this->assertEquals( $expected, $minified, "Line breaks must not occur in middle of exponent" ); 00169 } 00170 }