* (bug 32548) fix minification bug when numeric literal with exponent was split over...
authorBrion Vibber <brion@users.mediawiki.org>
Mon, 21 Nov 2011 23:16:36 +0000 (23:16 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Mon, 21 Nov 2011 23:16:36 +0000 (23:16 +0000)
This broke the OpenLayers support in the Maps extension, as used for example on TranslateWiki.net.
The original JavaScriptMinifier's tokenizer (r83885) explicitly didn't bother looking for the exponent part because it "didn't matter" to its internal state machine; however since r83891 added a max line length that definitely is not true.

I've split out handling of hex and decimal numerals, and let the decimal numeral handling check for exponents.

PHPUnit test cases were added in r103846.

includes/libs/JavaScriptMinifier.php

index a991d91..a45b103 100644 (file)
@@ -483,23 +483,34 @@ class JavaScriptMinifier {
                                while( $end < $length && ctype_alpha( $s[$end] ) ) {
                                        $end++;
                                }
+                       } elseif(
+                               $ch === '0'
+                               && ($pos + 1 < $length) && ($s[$pos + 1] === 'x' || $s[$pos + 1] === 'X' )
+                       ) {
+                               // Hex numeric literal
+                               $end++; // x or X
+                               $end += strspn( $s, '0123456789ABCDEF', $end );
+                               // @fixme if no hex digits, parse error
                        } elseif(
                                ctype_digit( $ch )
                                || ( $ch === '.' && $pos + 1 < $length && ctype_digit( $s[$pos + 1] ) )
                        ) {
-                               // Numeric literal. Search for the end of it, but don't care about [+-]exponent
-                               // at the end, as the results of "numeric [+-] numeric" and "numeric" are
-                               // identical to our state machine.
-                               $end += strspn( $s, '0123456789ABCDEFabcdefXx.', $end );
-                               while( $s[$end - 1] === '.' ) {
-                                       // Special case: When a numeric ends with a dot, we have to check the 
-                                       // literal for proper syntax
-                                       $decimal = strspn( $s, '0123456789', $pos, $end - $pos - 1 );
-                                       if( $decimal === $end - $pos - 1 ) {
-                                               break;
-                                       } else {
-                                               $end--;
-                                       }
+                               $end += strspn( $s, '0123456789', $end );
+                               $decimal = strspn( $s, '.', $end );
+                               if ($decimal) {
+                                       $end += $decimal;
+                                       $end += strspn( $s, '0123456789', $end );
+                                       // @fixme If no decimal digits after the . we cannot be followed
+                                       // by an identifier, and should throw a parse error
+                               }
+                               $exponent = strspn( $s, 'eE', $end );
+                               if( $exponent ) {
+                                       $end += $exponent;;
+                                       // + sign is optional; - sign is required.
+                                       $end += strspn( $s, '-+', $end );
+                                       $end += strspn( $s, '0123456789', $end );
+                                       // @fixme if no decimal digits after the e/+/- we should
+                                       // throw a parse error
                                }
                        } elseif( isset( $opChars[$ch] ) ) {
                                // Punctuation character. Search for the longest matching operator.