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