MediaWiki
REL1_23
|
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 00123 public function testJavaScriptMinifierOutput( $code, $expectedOutput ) { 00124 $minified = JavaScriptMinifier::minify( $code ); 00125 00126 // JSMin+'s parser will throw an exception if output is not valid JS. 00127 // suppression of warnings needed for stupid crap 00128 wfSuppressWarnings(); 00129 $parser = new JSParser(); 00130 wfRestoreWarnings(); 00131 $parser->parse( $minified, 'minify-test.js', 1 ); 00132 00133 $this->assertEquals( $expectedOutput, $minified, "Minified output should be in the form expected." ); 00134 } 00135 00136 public static function provideBug32548() { 00137 return array( 00138 array( 00139 // This one gets interpreted all together by the prior code; 00140 // no break at the 'E' happens. 00141 '1.23456789E55', 00142 ), 00143 array( 00144 // This one breaks under the bad code; splits between 'E' and '+' 00145 '1.23456789E+5', 00146 ), 00147 array( 00148 // This one breaks under the bad code; splits between 'E' and '-' 00149 '1.23456789E-5', 00150 ), 00151 ); 00152 } 00153 00159 public function testBug32548Exponent( $num ) { 00160 // Long line breaking was being incorrectly done between the base and 00161 // exponent part of a number, causing a syntax error. The line should 00162 // instead break at the start of the number. 00163 $prefix = 'var longVarName' . str_repeat( '_', 973 ) . '='; 00164 $suffix = ',shortVarName=0;'; 00165 00166 $input = $prefix . $num . $suffix; 00167 $expected = $prefix . "\n" . $num . $suffix; 00168 00169 $minified = JavaScriptMinifier::minify( $input ); 00170 00171 $this->assertEquals( $expected, $minified, "Line breaks must not occur in middle of exponent" ); 00172 } 00173 }