Use String#slice instead of String#substr or String#substring
authorTimo Tijhof <krinklemail@gmail.com>
Wed, 3 Sep 2014 15:19:41 +0000 (17:19 +0200)
committerOri.livneh <ori@wikimedia.org>
Wed, 3 Sep 2014 21:33:06 +0000 (21:33 +0000)
Quite a few reasons:

* There is a bug in IE 8 and below where the startIndex argument
  does not support negative values, contrary to the ECMAScript
  spec and implementations in other browsers.
  IE8:
    'faux'.substr( -1 ); // "faux"
  Standards:
    'faux'.substr( -1 ); // "x"

  Code written for ES5 (and using the es5-shim) works as expected
  since the shim repairs this method.

* String#substr and String#substring both exist but have
  different signatures which are easily mixed up.

  String.prototype.substr( start [, length] )
  > Supports negative start, but not in IE8 and below.
  > Takes length, *not* second index. E.g. `substr( 2, 3 )`
    returns `slice( 2, 5 )`.

  String.prototype.substring( indexA [, indexB] )
  > Doesn't support negative indices.
  > If indexA is larger than indexB, they are silently swapped!

  String.prototype.slice( start [, end] )
  > Supports negative indices.

    'faux'.substr( 0, 2 );     // "fa"
    'faux'.substring( 0, 2 );  // "fa"
    'faux'.slice( 0, 2 );      // "fa"

    'faux'.substr( -2 );       // "ux"
    'faux'.substring( -2 );    // "faux"
    'faux'.slice( -2 );        // "ux"

    'faux'.substr( 1, 2 );     // "au"
    'faux'.substring( 1, 2 );  // "a"
    'faux'.slice( 1, 2 );      // "a"

    'faux'.substr( 1, -1 );    // ""
    'faux'.substring( 1, -1 ); // "f"
    'faux'.slice( 1, -1 );     // "au"

    'faux'.substr( 2, 1 );     // "u"
    'faux'.substring( 2, 1 );  // "a"
    'faux'.slice( 2, 1 );      // ""

* String#slice works the same way as Array#slice and slice
  methods elsewhere (jQuery, PHP, ..).

* Also simplify calls:
  - Omit second argument where it explicitly calculated the length
    and passed it as is (default behaviour)
  - Pass negative values instead of length - x.
  - Use chatAt to extract a single character.

* Change:
  - Replace all uses of substring() with slice().
  - Replace all uses of substr() with slice() where only one
    parameter is passed or where the first parameter is 0.
  - Using substr()'s unique behaviour (length instead of endIndex)
    is fine, though there's only one instances of that, in
    mediawiki.jqueryMsg.js

Change-Id: I9b6dd682a64fa28c7ea0da1846ccd3b42f9430cf

26 files changed:
mw-config/config.js
resources/src/jquery/jquery.autoEllipsis.js
resources/src/jquery/jquery.byteLimit.js
resources/src/jquery/jquery.farbtastic.js
resources/src/jquery/jquery.hidpi.js
resources/src/jquery/jquery.mwExtension.js
resources/src/jquery/jquery.textSelection.js
resources/src/mediawiki.language/languages/fi.js
resources/src/mediawiki.language/languages/he.js
resources/src/mediawiki.language/languages/hy.js
resources/src/mediawiki.language/languages/os.js
resources/src/mediawiki.language/languages/ru.js
resources/src/mediawiki.language/languages/uk.js
resources/src/mediawiki.language/mediawiki.language.js
resources/src/mediawiki.language/mediawiki.language.numbers.js
resources/src/mediawiki.legacy/upload.js
resources/src/mediawiki.special/mediawiki.special.search.js
resources/src/mediawiki/mediawiki.Title.js
resources/src/mediawiki/mediawiki.debug.js
resources/src/mediawiki/mediawiki.debug.profile.js
resources/src/mediawiki/mediawiki.inspect.js
resources/src/mediawiki/mediawiki.jqueryMsg.js
resources/src/mediawiki/mediawiki.js
resources/src/mediawiki/mediawiki.user.js
tests/qunit/suites/resources/jquery/jquery.autoEllipsis.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.test.js

index 2886e08..cf17aef 100644 (file)
@@ -9,7 +9,7 @@
                                .replace( /__+/g, '_' )
                                .replace( /^_+/, '' )
                                .replace( /_+$/, '' );
-                       value = value.substr( 0, 1 ).toUpperCase() + value.substr( 1 );
+                       value = value.charAt( 0 ).toUpperCase() + value.slice( 1 );
                        $label.text( labelText.replace( '$1', value ) );
                }
 
index 061f5d6..9a196b5 100644 (file)
@@ -108,7 +108,7 @@ $.fn.autoEllipsis = function ( options ) {
                                        r = trimmableText.length;
                                        do {
                                                m = Math.ceil( ( l + r ) / 2 );
-                                               $trimmableText.text( trimmableText.substr( 0, m ) + '...' );
+                                               $trimmableText.text( trimmableText.slice( 0, m ) + '...' );
                                                if ( $trimmableText.width() + pw > w ) {
                                                        // Text is too long
                                                        r = m - 1;
@@ -116,7 +116,7 @@ $.fn.autoEllipsis = function ( options ) {
                                                        l = m;
                                                }
                                        } while ( l < r );
-                                       $trimmableText.text( trimmableText.substr( 0, l ) + '...' );
+                                       $trimmableText.text( trimmableText.slice( 0, l ) + '...' );
                                        break;
                                case 'center':
                                        // TODO: Use binary search like for 'right'
@@ -124,7 +124,7 @@ $.fn.autoEllipsis = function ( options ) {
                                        // Begin with making the end shorter
                                        side = 1;
                                        while ( $trimmableText.outerWidth() + pw > w && i[0] > 0 ) {
-                                               $trimmableText.text( trimmableText.substr( 0, i[0] ) + '...' + trimmableText.substr( i[1] ) );
+                                               $trimmableText.text( trimmableText.slice( 0, i[0] ) + '...' + trimmableText.slice( i[1] ) );
                                                // Alternate between trimming the end and begining
                                                if ( side === 0 ) {
                                                        // Make the begining shorter
@@ -141,7 +141,7 @@ $.fn.autoEllipsis = function ( options ) {
                                        // TODO: Use binary search like for 'right'
                                        r = 0;
                                        while ( $trimmableText.outerWidth() + pw > w && r < trimmableText.length ) {
-                                               $trimmableText.text( '...' + trimmableText.substr( r ) );
+                                               $trimmableText.text( '...' + trimmableText.slice( r ) );
                                                r++;
                                        }
                                        break;
index de05fdf..5551232 100644 (file)
 
                inpParts = [
                        // Same start
-                       newVal.substring( 0, startMatches ),
+                       newVal.slice( 0, startMatches ),
                        // Inserted content
-                       newVal.substring( startMatches, newVal.length - endMatches ),
+                       newVal.slice( startMatches, newVal.length - endMatches ),
                        // Same end
-                       newVal.substring( newVal.length - endMatches )
+                       newVal.slice( newVal.length - endMatches )
                ];
 
                // Chop off characters from the end of the "inserted content" string
index 1881085..d7024cc 100644 (file)
@@ -51,7 +51,7 @@ jQuery._farbtastic = function (container, callback) {
                $('*', e).each(function () {
                        if (this.currentStyle.backgroundImage != 'none') {
                                var image = this.currentStyle.backgroundImage;
-                               image = this.currentStyle.backgroundImage.substring(5, image.length - 2);
+                               image = this.currentStyle.backgroundImage.slice(5, image.length - 2);
                                $(this).css({
                                        'backgroundImage': 'none',
                                        'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
index 71b083b..4ecfeb8 100644 (file)
@@ -110,7 +110,7 @@ $.matchSrcSet = function ( devicePixelRatio, srcset ) {
                bits = candidate.split( / +/ );
                src = bits[0];
                if ( bits.length > 1 && bits[1].charAt( bits[1].length - 1 ) === 'x' ) {
-                       ratioStr = bits[1].substr( 0, bits[1].length - 1 );
+                       ratioStr = bits[1].slice( 0, -1 );
                        ratio = parseFloat( ratioStr );
                        if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
                                selectedRatio = ratio;
index cdcb8fb..dc7aaa4 100644 (file)
@@ -12,7 +12,7 @@
                                        '' : str.toString().replace( /\s+$/, '' );
                },
                ucFirst: function ( str ) {
-                       return str.charAt( 0 ).toUpperCase() + str.substr( 1 );
+                       return str.charAt( 0 ).toUpperCase() + str.slice( 1 );
                },
                escapeRE: function ( str ) {
                        return str.replace ( /([\\{}()|.?*+\-\^$\[\]])/g, '\\$1' );
index 289cd22..8d440fd 100644 (file)
                                                } else {
                                                        while ( selText.charAt( selText.length - 1 ) === ' ' ) {
                                                                // Exclude ending space char
-                                                               selText = selText.substring( 0, selText.length - 1 );
+                                                               selText = selText.slice( 0, -1 );
                                                                post += ' ';
                                                        }
                                                        while ( selText.charAt( 0 ) === ' ' ) {
                                                                // Exclude prepending space char
-                                                               selText = selText.substring( 1, selText.length );
+                                                               selText = selText.slice( 1 );
                                                                pre = ' ' + pre;
                                                        }
                                                }
                                                                        post += '\n';
                                                                }
                                                        }
-                                                       this.value = this.value.substring( 0, startPos ) + insertText +
-                                                               this.value.substring( endPos, this.value.length );
+                                                       this.value = this.value.slice( 0, startPos ) + insertText +
+                                                               this.value.slice( endPos );
                                                        // Setting this.value scrolls the textarea to the top, restore the scroll position
                                                        this.scrollTop = scrollTop;
                                                        if ( window.opera ) {
index 2382aae..453a675 100644 (file)
@@ -34,7 +34,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                        break;
                case 'illative':
                        // Double the last letter and add 'n'
-                       word += word.substr(  word.length - 1 ) + 'n';
+                       word += word.slice( -1 ) + 'n';
                        break;
                case 'inessive':
                        word += ( aou ? 'ssa' : 'ssä' );
index 48351bc..d1eba43 100644 (file)
@@ -11,17 +11,17 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                case 'prefixed':
                case 'תחילית': // the same word in Hebrew
                        // Duplicate prefixed "Waw", but only if it's not already double
-                       if ( word.substr( 0, 1 ) === 'ו' && word.substr( 0, 2 ) !== 'וו' ) {
+                       if ( word.slice( 0, 1 ) === 'ו' && word.slice( 0, 2 ) !== 'וו' ) {
                                word = 'ו' + word;
                        }
 
                        // Remove the "He" if prefixed
-                       if ( word.substr( 0, 1 ) === 'ה' ) {
-                               word = word.substr( 1, word.length );
+                       if ( word.slice( 0, 1 ) === 'ה' ) {
+                               word = word.slice( 1 );
                        }
 
                        // Add a hyphen (maqaf) before numbers and non-Hebrew letters
-                       if ( word.substr( 0, 1 ) < 'א' ||  word.substr( 0, 1 ) > 'ת' ) {
+                       if ( word.slice( 0, 1 ) < 'א' ||  word.slice( 0, 1 ) > 'ת' ) {
                                word = '־' + word;
                        }
        }
index ae16f24..9cae360 100644 (file)
@@ -14,12 +14,12 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
 
        switch ( form ) {
                case 'genitive': // սեռական հոլով
-                       if ( word.substr( -1 ) === 'ա' ) {
-                               word = word.substr( 0, word.length - 1 ) + 'այի';
-                       } else if ( word.substr( -1 ) === 'ո' ) {
-                               word = word.substr( 0, word.length - 1 ) + 'ոյի';
-                       } else if ( word.substr( -4 ) === 'գիրք' ) {
-                               word = word.substr( 0, word.length - 4 ) + 'գրքի';
+                       if ( word.slice( -1 ) === 'ա' ) {
+                               word = word.slice( 0, -1 ) + 'այի';
+                       } else if ( word.slice( -1 ) === 'ո' ) {
+                               word = word.slice( 0, -1 ) + 'ոյի';
+                       } else if ( word.slice( -4 ) === 'գիրք' ) {
+                               word = word.slice( 0, -4 ) + 'գրքի';
                        } else {
                                word = word + 'ի';
                        }
index bdf59be..787be36 100644 (file)
@@ -19,7 +19,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
        }
        // Checking if the $word is in plural form
        if ( word.match( /тæ$/i ) ) {
-               word = word.substring( 0, word.length - 1 );
+               word = word.slice( 0, -1 );
                endAllative = 'æм';
        }
        // Works if word is in singular form.
@@ -30,7 +30,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
        // Checking if word ends on 'у'. 'У' can be either consonant 'W' or vowel 'U' in cyrillic Ossetic.
        // Examples: {{grammar:genitive|аунеу}} = аунеуы, {{grammar:genitive|лæппу}} = лæппуйы.
        else if ( word.match( /у$/i ) ) {
-               if ( !word.substring( word.length - 2, word.length - 1 ).match( /[аæеёиоыэюя]$/i ) ) {
+               if ( !word.slice( -2, -1 ).match( /[аæеёиоыэюя]$/i ) ) {
                        jot = 'й';
                }
        } else if ( !word.match( /[бвгджзйклмнопрстфхцчшщьъ]$/i ) ) {
index b6ba59f..2077b6b 100644 (file)
@@ -15,41 +15,41 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
        }
        switch ( form ) {
                case 'genitive': // родительный падеж
-                       if ( word.substr( word.length - 1 ) === 'ь' ) {
-                               word = word.substr(0, word.length - 1 ) + 'я';
-                       } else if ( word.substr( word.length - 2 ) === 'ия' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ии';
-                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ки';
-                       } else if ( word.substr( word.length - 2 )  === 'ти' ) {
-                               word = word.substr(0, word.length - 2 ) + 'тей';
-                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
-                               word = word.substr(0, word.length - 2 ) + 'дов';
-                       } else if ( word.substr( word.length - 1 ) === 'д' ) {
-                               word = word.substr(0, word.length - 1 ) + 'да';
-                       } else if ( word.substr( word.length - 3 ) === 'ные' ) {
-                               word = word.substr(0, word.length - 3 ) + 'ных';
-                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
-                               word = word.substr(0, word.length - 3 ) + 'ника';
+                       if ( word.slice( -1 ) === 'ь' ) {
+                               word = word.slice( 0, -1 ) + 'я';
+                       } else if ( word.slice( -2 ) === 'ия' ) {
+                               word = word.slice( 0, -2 ) + 'ии';
+                       } else if ( word.slice( -2 ) === 'ка' ) {
+                               word = word.slice( 0, -2 ) + 'ки';
+                       } else if ( word.slice( -2 ) === 'ти' ) {
+                               word = word.slice( 0, -2 ) + 'тей';
+                       } else if ( word.slice( -2 ) === 'ды' ) {
+                               word = word.slice( 0, -2 ) + 'дов';
+                       } else if ( word.slice( -1 ) === 'д' ) {
+                               word = word.slice( 0, -1 ) + 'да';
+                       } else if ( word.slice( -3 ) === 'ные' ) {
+                               word = word.slice( 0, -3 ) + 'ных';
+                       } else if ( word.slice( -3 ) === 'ник' ) {
+                               word = word.slice( 0, -3 ) + 'ника';
                        }
                        break;
                case 'prepositional': // предложный падеж
-                       if ( word.substr( word.length - 1 ) === 'ь' ) {
-                               word = word.substr(0, word.length - 1 ) + 'е';
-                       } else if ( word.substr( word.length - 2 ) === 'ия' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ии';
-                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ке';
-                       } else if ( word.substr( word.length - 2 )  === 'ти' ) {
-                               word = word.substr(0, word.length - 2 ) + 'тях';
-                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
-                               word = word.substr(0, word.length - 2 ) + 'дах';
-                       } else if ( word.substr( word.length - 1 ) === 'д' ) {
-                               word = word.substr(0, word.length - 1 ) + 'де';
-                       } else if ( word.substr( word.length - 3 ) === 'ные' ) {
-                               word = word.substr(0, word.length - 3 ) + 'ных';
-                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
-                               word = word.substr(0, word.length - 3 ) + 'нике';
+                       if ( word.slice( -1 ) === 'ь' ) {
+                               word = word.slice( 0, -1 ) + 'е';
+                       } else if ( word.slice( -2 ) === 'ия' ) {
+                               word = word.slice( 0, -2 ) + 'ии';
+                       } else if ( word.slice( -2 ) === 'ка' ) {
+                               word = word.slice( 0, -2 ) + 'ке';
+                       } else if ( word.slice( -2 ) === 'ти' ) {
+                               word = word.slice( 0, -2 ) + 'тях';
+                       } else if ( word.slice( -2 ) === 'ды' ) {
+                               word = word.slice( 0, -2 ) + 'дах';
+                       } else if ( word.slice( -1 ) === 'д' ) {
+                               word = word.slice( 0, -1 ) + 'де';
+                       } else if ( word.slice( -3 ) === 'ные' ) {
+                               word = word.slice( 0, -3 ) + 'ных';
+                       } else if ( word.slice( -3 ) === 'ник' ) {
+                               word = word.slice( 0, -3 ) + 'нике';
                        }
                        break;
        }
index 69f7ec5..550a388 100644 (file)
@@ -9,26 +9,26 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
        }
        switch ( form ) {
                case 'genitive': // родовий відмінок
-                       if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) {
-                               if ( word.substr( word.length - 1 ) === 'ь' ) {
-                                       word = word.substr(0, word.length - 1 ) + 'я';
-                               } else if ( word.substr( word.length - 2 ) === 'ія' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'ії';
-                               } else if ( word.substr( word.length - 2 ) === 'ка' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'ки';
-                               } else if ( word.substr( word.length - 2 ) === 'ти' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'тей';
-                               } else if ( word.substr( word.length - 2 ) === 'ды' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'дов';
-                               } else if ( word.substr( word.length - 3 ) === 'ник' ) {
-                                       word = word.substr(0, word.length - 3 ) + 'ника';
+                       if ( word.slice( -4 ) !== 'вікі' && word.slice( -4 ) !== 'Вікі' ) {
+                               if ( word.slice( -1 ) === 'ь' ) {
+                                       word = word.slice(0, -1 ) + 'я';
+                               } else if ( word.slice( -2 ) === 'ія' ) {
+                                       word = word.slice(0, -2 ) + 'ії';
+                               } else if ( word.slice( -2 ) === 'ка' ) {
+                                       word = word.slice(0, -2 ) + 'ки';
+                               } else if ( word.slice( -2 ) === 'ти' ) {
+                                       word = word.slice(0, -2 ) + 'тей';
+                               } else if ( word.slice( -2 ) === 'ды' ) {
+                                       word = word.slice(0, -2 ) + 'дов';
+                               } else if ( word.slice( -3 ) === 'ник' ) {
+                                       word = word.slice(0, -3 ) + 'ника';
                                }
                        }
                        break;
                case 'accusative': // знахідний відмінок
-                       if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) {
-                               if ( word.substr( word.length - 2 ) === 'ія' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'ію';
+                       if ( word.slice( -4 ) !== 'вікі' && word.slice( -4 ) !== 'Вікі' ) {
+                               if ( word.slice( -2 ) === 'ія' ) {
+                                       word = word.slice(0, -2 ) + 'ію';
                                }
                        }
                        break;
index 2e84858..d4f3c69 100644 (file)
@@ -59,9 +59,9 @@ $.extend( mw.language, {
                        form = forms[index];
                        if ( /^\d+=/.test( form ) ) {
                                equalsPosition = form.indexOf( '=' );
-                               formCount = parseInt( form.substring( 0, equalsPosition ), 10 );
+                               formCount = parseInt( form.slice( 0, equalsPosition ), 10 );
                                if ( formCount === count ) {
-                                       return form.substr( equalsPosition + 1 );
+                                       return form.slice( equalsPosition + 1 );
                                }
                                forms[index] = undefined;
                        }
index 8bd2de9..a0b8141 100644 (file)
 
                        // Truncate fractional
                        if ( maxPlaces < fractional.length ) {
-                               valueParts[1] = fractional.substr( 0, maxPlaces );
+                               valueParts[1] = fractional.slice( 0, maxPlaces );
                        }
                } else {
                        if ( valueParts[1] ) {
 
                        // Truncate whole
                        if ( patternDigits.indexOf( '#' ) === -1 ) {
-                               valueParts[0] = valueParts[0].substr( valueParts[0].length - padLength );
+                               valueParts[0] = valueParts[0].slice( valueParts[0].length - padLength );
                        }
                }
 
 
                if ( index !== -1 ) {
                        groupSize = patternParts[0].length - index - 1;
-                       remainder = patternParts[0].substr( 0, index );
+                       remainder = patternParts[0].slice( 0, index );
                        index = remainder.lastIndexOf( ',' );
                        if ( index !== -1 ) {
                                groupSize2 = remainder.length - index - 1;
 
                for ( whole = valueParts[0]; whole; ) {
                        off = groupSize ? whole.length - groupSize : 0;
-                       pieces.push( ( off > 0 ) ? whole.substr( off ) : whole );
+                       pieces.push( ( off > 0 ) ? whole.slice( off ) : whole );
                        whole = ( off > 0 ) ? whole.slice( 0, off ) : '';
 
                        if ( groupSize2 ) {
index 144bdf9..c81b388 100644 (file)
                                if ( slash === -1 && backslash === -1 ) {
                                        fname = path;
                                } else if ( slash > backslash ) {
-                                       fname = path.substring( slash + 1 );
+                                       fname = path.slice( slash + 1 );
                                } else {
-                                       fname = path.substring( backslash + 1 );
+                                       fname = path.slice( backslash + 1 );
                                }
 
                                // Clear the filename if it does not have a valid extension.
                                        if (
                                                fname.lastIndexOf( '.' ) === -1 ||
                                                $.inArray(
-                                                       fname.substr( fname.lastIndexOf( '.' ) + 1 ).toLowerCase(),
+                                                       fname.slice( fname.lastIndexOf( '.' ) + 1 ).toLowerCase(),
                                                        $.map( mw.config.get( 'wgFileExtensions' ), function ( element ) {
                                                                return element.toLowerCase();
                                                        } )
                                fname = fname.replace( / /g, '_' );
                                // Capitalise first letter if needed
                                if ( mw.config.get( 'wgCapitalizeUploads' ) ) {
-                                       fname = fname.charAt( 0 ).toUpperCase().concat( fname.substring( 1 ) );
+                                       fname = fname.charAt( 0 ).toUpperCase().concat( fname.slice( 1 ) );
                                }
 
                                // Output result
index a4128f9..b27fe34 100644 (file)
@@ -39,8 +39,8 @@
                                var parts = $( this ).attr( 'href' ).split( 'search=' ),
                                        lastpart = '',
                                        prefix = 'search=';
-                               if ( parts.length > 1 && parts[1].indexOf( '&' ) >= 0 ) {
-                                       lastpart = parts[1].substring( parts[1].indexOf( '&' ) );
+                               if ( parts.length > 1 && parts[1].indexOf( '&' ) !== -1 ) {
+                                       lastpart = parts[1].slice( parts[1].indexOf( '&' ) );
                                } else {
                                        prefix = '&search=';
                                }
index 4387608..fc8e7e9 100644 (file)
                        namespace = NS_MAIN;
                        title = title
                                // Strip colon
-                               .substr( 1 )
+                               .slice( 1 )
                                // Trim underscores
                                .replace( rUnderscoreTrim, '' );
                }
                } else {
                        fragment = title
                                // Get segment starting after the hash
-                               .substr( i + 1 )
+                               .slice( i + 1 )
                                // Convert to text
                                // NB: Must not be trimmed ("Example#_foo" is not the same as "Example#foo")
                                .replace( /_/g, ' ' );
 
                        title = title
                                // Strip hash
-                               .substr( 0, i )
+                               .slice( 0, i )
                                // Trim underscores, again (strips "_" from "bar" in "Foo_bar_#quux")
                                .replace( rUnderscoreTrim, '' );
                }
                                title.indexOf( '../' ) === 0 ||
                                title.indexOf( '/./' ) !== -1 ||
                                title.indexOf( '/../' ) !== -1 ||
-                               title.substr( title.length - 2 ) === '/.' ||
-                               title.substr( title.length - 3 ) === '/..'
+                               title.slice( -2 ) === '/.' ||
+                               title.slice( -3 ) === '/..'
                        )
                ) {
                        return false;
                        // Extensions are the non-empty segment after the last dot
                        ext = null;
                } else {
-                       ext = title.substr( i + 1 );
-                       title = title.substr( 0, i );
+                       ext = title.slice( i + 1 );
+                       title = title.slice( 0, i );
                }
 
                return {
index 505a9be..4935984 100644 (file)
@@ -61,7 +61,7 @@
                 */
                switchPane: function ( e ) {
                        var currentPaneId = debug.$container.data( 'currentPane' ),
-                               requestedPaneId = $( this ).prop( 'id' ).substr( 9 ),
+                               requestedPaneId = $( this ).prop( 'id' ).slice( 9 ),
                                $currentPane = $( '#mw-debug-pane-' + currentPaneId ),
                                $requestedPane = $( '#mw-debug-pane-' + requestedPaneId ),
                                hovDone = false;
 
                        gitInfo = '';
                        if ( this.data.gitRevision !== false ) {
-                               gitInfo = '(' + this.data.gitRevision.substring( 0, 7 ) + ')';
+                               gitInfo = '(' + this.data.gitRevision.slice( 0, 7 ) + ')';
                                if ( this.data.gitViewUrl !== false ) {
                                        gitInfo = $( '<a>' )
                                                .attr( 'href', this.data.gitViewUrl )
index b4d5773..7bbbbd3 100644 (file)
        ProfileData.groupOf = function ( label ) {
                var pos, prefix = 'Profile section ended by close(): ';
                if ( label.indexOf( prefix ) === 0 ) {
-                       label = label.substring( prefix.length );
+                       label = label.slice( prefix.length );
                }
 
                pos = [ '::', ':', '-' ].reduce( function ( result, separator ) {
                if ( pos === -1 ) {
                        return label;
                } else {
-                       return label.substring( 0, pos );
+                       return label.slice( 0, pos );
                }
        };
 
index eda7689..8e9fc89 100644 (file)
                },
 
                /**
-                * Perform a substring search across the JavaScript and CSS source code
+                * Perform a string search across the JavaScript and CSS source code
                 * of all loaded modules and return an array of the names of the
                 * modules that matched.
                 *
index a81730e..ad71b08 100644 (file)
                         */
                        function makeRegexParser( regex ) {
                                return function () {
-                                       var matches = input.substr( pos ).match( regex );
+                                       var matches = input.slice( pos ).match( regex );
                                        if ( matches === null ) {
                                                return null;
                                        }
 
                                if ( parsedCloseTagResult === null ) {
                                        // Closing tag failed.  Return the start tag and contents.
-                                       return [ 'CONCAT', input.substring( startOpenTagPos, endOpenTagPos ) ]
+                                       return [ 'CONCAT', input.slice( startOpenTagPos, endOpenTagPos ) ]
                                                .concat( parsedHtmlContents );
                                }
 
                                        // parsed HTML link.
                                        //
                                        // Concatenate everything from the tag, flattening the contents.
-                                       result = [ 'CONCAT', input.substring( startOpenTagPos, endOpenTagPos ) ]
-                                               .concat( parsedHtmlContents, input.substring( startCloseTagPos, endCloseTagPos ) );
+                                       result = [ 'CONCAT', input.slice( startOpenTagPos, endOpenTagPos ) ]
+                                               .concat( parsedHtmlContents, input.slice( startCloseTagPos, endCloseTagPos ) );
                                }
 
                                return result;
index d50fe48..5e5a3ac 100644 (file)
                                                        for ( i = 0; i < modules.length; i += 1 ) {
                                                                // Determine how many bytes this module would add to the query string
                                                                lastDotIndex = modules[i].lastIndexOf( '.' );
-                                                               // Note that these substr() calls work even if lastDotIndex == -1
+
+                                                               // If lastDotIndex is -1, substr() returns an empty string
                                                                prefix = modules[i].substr( 0, lastDotIndex );
-                                                               suffix = modules[i].substr( lastDotIndex + 1 );
+                                                               suffix = modules[i].slice( lastDotIndex + 1 );
+
                                                                bytesAdded = moduleMap[prefix] !== undefined
                                                                        ? suffix.length + 3 // '%2C'.length == 3
                                                                        : modules[i].length + 3; // '%7C'.length == 3
                                                }
 
                                                for ( key in mw.loader.store.items ) {
-                                                       module = key.substring( 0, key.indexOf( '@' ) );
+                                                       module = key.slice( 0, key.indexOf( '@' ) );
                                                        if ( mw.loader.store.getModuleKey( module ) !== key ) {
                                                                mw.loader.store.stats.expired++;
                                                                delete mw.loader.store.items[key];
index 7933f1d..e93707e 100644 (file)
@@ -62,7 +62,7 @@
                                seed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
                        for ( i = 0; i < 32; i++ ) {
                                r = Math.floor( Math.random() * seed.length );
-                               id += seed.substring( r, r + 1 );
+                               id += seed.charAt( r );
                        }
                        return id;
                },
index 1005316..e8c5121 100644 (file)
@@ -41,7 +41,7 @@
                // Add two characters using scary black magic
                spanText = $span.text();
                d = findDivergenceIndex( origText, spanText );
-               spanTextNew = spanText.substr( 0, d ) + origText[d] + origText[d] + '...';
+               spanTextNew = spanText.slice( 0, d ) + origText[d] + origText[d] + '...';
 
                assert.gt( spanTextNew.length, spanText.length, 'Verify that the new span-length is indeed greater' );
 
index 9681330..5bcd57b 100644 (file)
                // Confirm that mw.loader.load() works with protocol-relative URLs
                target = target.replace( /https?:/, '' );
 
-               assert.equal( target.substr( 0, 2 ), '//',
+               assert.equal( target.slice( 0, 2 ), '//',
                        'URL must be relative to test relative URLs!'
                );