function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
  var resultArray = reusableReplaceArray;
  if (resultArray) {
    reusableReplaceArray = null;
  } else {
    // Inside a nested replace (replace called from the replacement function
    // of another replace) or we have failed to set the reusable array
    // back due to an exception in a replacement function. Create a new
    // array to use in the future, or until the original is written back.
    resultArray = new InternalArray(16);
  }
  var res = %RegExpExecMultiple(regexp,
                                subject,
                                RegExpLastMatchInfo,
                                resultArray);
  regexp.lastIndex = 0;
  if (IS_NULL(res)) {
    // No matches at all.
    reusableReplaceArray = resultArray;
    return subject;
  }
  var len = res.length;
  if (NUMBER_OF_CAPTURES(RegExpLastMatchInfo) == 2) {
    // If the number of captures is two then there are no explicit captures in
    // the regexp, just the implicit capture that captures the whole match.  In
    // this case we can simplify quite a bit and end up with something faster.
    // The builder will consist of some integers that indicate slices of the
    // input string and some replacements that were returned from the replace
    // function.
    var match_start = 0;
    for (var i = 0; i < len; i++) {
      var elem = res[i];
      if (%_IsSmi(elem)) {
        // Integers represent slices of the original string.
        if (elem > 0) {
          match_start = (elem >> 11) + (elem & 0x7ff);
        } else {
          match_start = res[++i] - elem;
        }
      } else {
        var func_result = replace(elem, match_start, subject);
        // Overwrite the i'th element in the results with the string we got
        // back from the callback function.
        res[i] = TO_STRING(func_result);
        match_start += elem.length;
      }
    }
  } else {
    for (var i = 0; i < len; i++) {
      var elem = res[i];
      if (!%_IsSmi(elem)) {
        // elem must be an Array.
        // Use the apply argument as backing for global RegExp properties.
        var func_result = %reflect_apply(replace, UNDEFINED, elem);
        // Overwrite the i'th element in the results with the string we got
        // back from the callback function.
        res[i] = TO_STRING(func_result);
      }
    }
  }
  var result = %StringBuilderConcat(res, len, subject);
  resultArray.length = 0;
  reusableReplaceArray = resultArray;
  return result;
}
function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
  var resultArray = reusableReplaceArray;
  if (resultArray) {
    reusableReplaceArray = null;
  } else {
    
    
    
    
    resultArray = new InternalArray(16);
  }
  var res = %RegExpExecMultiple(regexp,
                                subject,
                                RegExpLastMatchInfo,
                                resultArray);
  regexp.lastIndex = 0;
  if (IS_NULL(res)) {
    
    reusableReplaceArray = resultArray;
    return subject;
  }
  var len = res.length;
  if (NUMBER_OF_CAPTURES(RegExpLastMatchInfo) == 2) {
    
    
    
    
    
    
    var match_start = 0;
    for (var i = 0; i < len; i++) {
      var elem = res[i];
      if (%_IsSmi(elem)) {
        
        if (elem > 0) {
          match_start = (elem >> 11) + (elem & 0x7ff);
        } else {
          match_start = res[++i] - elem;
        }
      } else {
        var func_result = replace(elem, match_start, subject);
        
        
        res[i] = TO_STRING(func_result);
        match_start += elem.length;
      }
    }
  } else {
    for (var i = 0; i < len; i++) {
      var elem = res[i];
      if (!%_IsSmi(elem)) {
        
        
        var func_result = %reflect_apply(replace, UNDEFINED, elem);
        
        
        res[i] = TO_STRING(func_result);
      }
    }
  }
  var result = %StringBuilderConcat(res, len, subject);
  resultArray.length = 0;
  reusableReplaceArray = resultArray;
  return result;
}
function StringReplaceGlobalRegExpWithFunction ( subject , regexp , replace ) { var resultArray = reusableReplaceArray ; if ( resultArray ) { reusableReplaceArray = null ; } else { // Inside a nested replace (replace called from the replacement function // of another replace) or we have failed to set the reusable array // back due to an exception in a replacement function. Create a new // array to use in the future, or until the original is written back. resultArray = new InternalArray ( 16 ) ; } var res = % RegExpExecMultiple ( regexp , subject , RegExpLastMatchInfo , resultArray ) ; regexp . lastIndex = 0 ; if ( IS_NULL ( res ) ) { // No matches at all. reusableReplaceArray = resultArray ; return subject ; } var len = res . length ; if ( NUMBER_OF_CAPTURES ( RegExpLastMatchInfo ) == 2 ) { // If the number of captures is two then there are no explicit captures in // the regexp, just the implicit capture that captures the whole match.  In // this case we can simplify quite a bit and end up with something faster. // The builder will consist of some integers that indicate slices of the // input string and some replacements that were returned from the replace // function. var match_start = 0 ; for ( var i = 0 ; i < len ; i ++ ) { var elem = res [ i ] ; if ( % _IsSmi ( elem ) ) { // Integers represent slices of the original string. if ( elem > 0 ) { match_start = ( elem >> 11 ) + ( elem & 0x7ff ) ; } else { match_start = res [ ++ i ] - elem ; } } else { var func_result = replace ( elem , match_start , subject ) ; // Overwrite the i'th element in the results with the string we got // back from the callback function. res [ i ] = TO_STRING ( func_result ) ; match_start += elem . length ; } } } else { for ( var i = 0 ; i < len ; i ++ ) { var elem = res [ i ] ; if ( ! % _IsSmi ( elem ) ) { // elem must be an Array. // Use the apply argument as backing for global RegExp properties. var func_result = % reflect_apply ( replace , UNDEFINED , elem ) ; // Overwrite the i'th element in the results with the string we got // back from the callback function. res [ i ] = TO_STRING ( func_result ) ; } } } var result = % StringBuilderConcat ( res , len , subject ) ; resultArray . length = 0 ; reusableReplaceArray = resultArray ; return result ; }
Helper function for replacing regular expressions with the result of a function application in String.prototype.replace.
Helper function for replacing regular expressions with the result of a function application in String . prototype . replace .