Merge "resourceloader: Make various CSSMin performance optimizations and cleanups"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 17 May 2018 18:50:45 +0000 (18:50 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 17 May 2018 18:50:45 +0000 (18:50 +0000)
1  2 
includes/libs/CSSMin.php
tests/phpunit/includes/libs/CSSMinTest.php

diff --combined includes/libs/CSSMin.php
@@@ -40,7 -40,7 +40,7 @@@ class CSSMin 
        const EMBED_REGEX = '\/\*\s*\@embed\s*\*\/';
        const COMMENT_REGEX = '\/\*.*?\*\/';
  
-       /** @var array List of common image files extensions and MIME-types */
+       /** @var string[] List of common image files extensions and MIME-types */
        protected static $mimeTypes = [
                'gif' => 'image/gif',
                'jpe' => 'image/jpeg',
@@@ -58,7 -58,7 +58,7 @@@
         *
         * @param string $source CSS stylesheet source to process
         * @param string $path File path where the source was read from
-        * @return array List of local file references
+        * @return string[] List of local file references
         */
        public static function getLocalFileReferences( $source, $path ) {
                $stripped = preg_replace( '/' . self::COMMENT_REGEX . '/s', '', $source );
         * @param bool $ie8Compat By default, a data URI will only be produced if it can be made short
         *     enough to fit in Internet Explorer 8 (and earlier) URI length limit (32,768 bytes). Pass
         *     `false` to remove this limitation.
-        * @return string|bool Image contents encoded as a data URI or false.
+        * @return string|false Image contents encoded as a data URI or false.
         */
        public static function encodeImageAsDataURI( $file, $type = null, $ie8Compat = true ) {
                // Fast-fail for files that definitely exceed the maximum data URI length
         * @param string $contents File contents to encode.
         * @param string $type File's MIME type.
         * @param bool $ie8Compat See encodeImageAsDataURI().
-        * @return string|bool Image contents encoded as a data URI or false.
+        * @return string|false Image contents encoded as a data URI or false.
         */
        public static function encodeStringAsDataURI( $contents, $type, $ie8Compat = true ) {
                // Try #1: Non-encoded data URI
  
        /**
         * Serialize a string (escape and quote) for use as a CSS string value.
 -       * https://www.w3.org/TR/2016/WD-cssom-1-20160317/#serialize-a-string
 +       * https://drafts.csswg.org/cssom/#serialize-a-string
         *
         * @param string $value
         * @return string
         */
        public static function serializeStringValue( $value ) {
 -              $value = strtr( $value, [ "\0" => "\\fffd ", '\\' => '\\\\', '"' => '\\"' ] );
 +              $value = strtr( $value, [ "\0" => "\xEF\xBF\xBD", '\\' => '\\\\', '"' => '\\"' ] );
                $value = preg_replace_callback( '/[\x01-\x1f\x7f]/', function ( $match ) {
                        return '\\' . base_convert( ord( $match[0] ), 10, 16 ) . ' ';
                }, $value );
         * @return bool
         */
        protected static function isLocalUrl( $maybeUrl ) {
-               if ( $maybeUrl !== '' && $maybeUrl[0] === '/' && !self::isRemoteUrl( $maybeUrl ) ) {
-                       return true;
-               }
-               return false;
+               return isset( $maybeUrl[1] ) && $maybeUrl[0] === '/' && $maybeUrl[1] !== '/';
        }
  
        /**
                        //   is only supported in PHP 5.6. Use a getter method for now.
                        $urlRegex = '(' .
                                // Unquoted url
 -                              'url\(\s*(?P<file0>[^\'"][^\?\)]+?)(?P<query0>\?[^\)]*?|)\s*\)' .
 +                              'url\(\s*(?P<file0>[^\s\'"][^\?\)]+?)(?P<query0>\?[^\)]*?|)\s*\)' .
                                // Single quoted url
                                '|url\(\s*\'(?P<file1>[^\?\']+?)(?P<query1>\?[^\']*?|)\'\s*\)' .
                                // Double quoted url
                                                return $data;
                                        }
                                }
-                               if ( method_exists( 'OutputPage', 'transformFilePath' ) ) {
+                               if ( class_exists( OutputPage::class ) ) {
                                        $url = OutputPage::transformFilePath( $remote, $local, $file );
                                } else {
                                        // Add version parameter as the first five hex digits
@@@ -35,7 -35,7 +35,7 @@@ class CSSMinTest extends MediaWikiTestC
        public static function provideSerializeStringValue() {
                return [
                        [ 'Hello World!', '"Hello World!"' ],
 -                      [ "Null\0Null", "\"Null\\fffd Null\"" ],
 +                      [ "Null\0Null", "\"Null\xEF\xBF\xBDNull\"" ],
                        [ '"', '"\\""' ],
                        [ "'", '"\'"' ],
                        [ "\\", '"\\\\"' ],
                        [ true, '//example.org/x.y.z/image.png' ],
                        [ true, '//localhost/styles.css?query=yes' ],
                        [ true, 'data:image/gif;base64,R0lGODlhAQABAIAAAP8AADAAACwAAAAAAQABAAACAkQBADs=' ],
+                       [ false, '' ],
+                       [ false, '/' ],
+                       [ true, '//' ],
                        [ false, 'x.gif' ],
                        [ false, '/x.gif' ],
                        [ false, './x.gif' ],
  
        public static function provideIsLocalUrls() {
                return [
+                       [ false, '' ],
+                       [ false, '/' ],
+                       [ false, '//' ],
                        [ false, 'x.gif' ],
                        [ true, '/x.gif' ],
                        [ false, './x.gif' ],
                                [ 'background-image: url("");', false, '/example', false ],
                                'background-image: url("");',
                        ],
 +                      'Single quote with outer spacing' => [
 +                              [ "background-image: url( '' );", false, '/example', false ],
 +                              "background-image: url( '' );",
 +                      ],
                ];
        }
  
                                'foo { background: url(/static/foo.png?query=yes); }',
                                'foo { background: url(https://expand.example/static/foo.png?query=yes); }',
                        ],
 +                      [
 +                              'Path-relative URL with query',
 +                              "foo { background: url(?query=yes); }",
 +                              'foo { background: url(http://localhost/w/?query=yes); }',
 +                      ],
                        [
                                'Remote URL (unnecessary quotes not preserved)',
                                'foo { background: url("http://example.org/w/unnecessary-quotes.png"); }',
                                'foo { background: url(//localhost/styles.css?quoted=single) }',
                        ],
                        [
 -                              'Background URL (containing parentheses; T60473)',
 +                              'Background URL (double quoted, containing parentheses; T60473)',
                                'foo { background: url("//localhost/styles.css?query=(parens)") }',
                                'foo { background: url("//localhost/styles.css?query=(parens)") }',
                        ],
                                'foo { background: url(\'//localhost/styles.css?quote="\') }',
                                'foo { background: url("//localhost/styles.css?quote=\"") }',
                        ],
 +                      [
 +                              'Background URL (double quoted with outer spacing)',
 +                              'foo { background: url( "http://localhost/styles.css?quoted=double" ) }',
 +                              'foo { background: url(http://localhost/styles.css?quoted=double) }',
 +                      ],
 +                      [
 +                              'Background URL (single quoted, containing spaces, with outer spacing)',
 +                              "foo { background: url( ' red.gif ' ); }",
 +                              'foo { background: url("http://localhost/w/ red.gif "); }',
 +                      ],
                        [
                                'Simple case with comments before url',
                                'foo { prop: /* some {funny;} comment */ url(bar.png); }',