function StringReplace(search, replace) {
  CHECK_OBJECT_COERCIBLE(this, "String.prototype.replace");

  // Decision tree for dispatch
  // .. regexp search (in src/js/regexp.js, RegExpReplace)
  // .... string replace
  // ...... non-global search
  // ........ empty string replace
  // ........ non-empty string replace (with $-expansion)
  // ...... global search
  // ........ no need to circumvent last match info override
  // ........ need to circument last match info override
  // .... function replace
  // ...... global search
  // ...... non-global search
  // .. string search
  // .... special case that replaces with one single character
  // ...... function replace
  // ...... string replace (with $-expansion)

  if (!IS_NULL_OR_UNDEFINED(search)) {
    var replacer = search[replaceSymbol];
    if (!IS_UNDEFINED(replacer)) {
      return %_Call(replacer, search, this, replace);
    }
  }

  var subject = TO_STRING(this);

  search = TO_STRING(search);

  if (search.length == 1 &&
      subject.length > 0xFF &&
      IS_STRING(replace) &&
      %StringIndexOf(replace, '$', 0) < 0) {
    // Searching by traversing a cons string tree and replace with cons of
    // slices works only when the replaced string is a single character, being
    // replaced by a simple string and only pays off for long strings.
    return %StringReplaceOneCharWithString(subject, search, replace);
  }
  var start = %StringIndexOf(subject, search, 0);
  if (start < 0) return subject;
  var end = start + search.length;

  var result = %_SubString(subject, 0, start);

  // Compute the string to replace with.
  if (IS_CALLABLE(replace)) {
    result += replace(search, start, subject);
  } else {
    reusableMatchInfo[CAPTURE0] = start;
    reusableMatchInfo[CAPTURE1] = end;
    result = ExpandReplacement(TO_STRING(replace),
                               subject,
                               reusableMatchInfo,
                               result);
  }

  return result + %_SubString(subject, end, subject.length);
}
function StringReplace(search, replace) {
  CHECK_OBJECT_COERCIBLE(this, "String.prototype.replace");

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  

  if (!IS_NULL_OR_UNDEFINED(search)) {
    var replacer = search[replaceSymbol];
    if (!IS_UNDEFINED(replacer)) {
      return %_Call(replacer, search, this, replace);
    }
  }

  var subject = TO_STRING(this);

  search = TO_STRING(search);

  if (search.length == 1 &&
      subject.length > 0xFF &&
      IS_STRING(replace) &&
      %StringIndexOf(replace, '$', 0) < 0) {
    
    
    
    return %StringReplaceOneCharWithString(subject, search, replace);
  }
  var start = %StringIndexOf(subject, search, 0);
  if (start < 0) return subject;
  var end = start + search.length;

  var result = %_SubString(subject, 0, start);

  
  if (IS_CALLABLE(replace)) {
    result += replace(search, start, subject);
  } else {
    reusableMatchInfo[CAPTURE0] = start;
    reusableMatchInfo[CAPTURE1] = end;
    result = ExpandReplacement(TO_STRING(replace),
                               subject,
                               reusableMatchInfo,
                               result);
  }

  return result + %_SubString(subject, end, subject.length);
}
function StringReplace ( search , replace ) { CHECK_OBJECT_COERCIBLE ( this , "String.prototype.replace" ) ; // Decision tree for dispatch // .. regexp search (in src/js/regexp.js, RegExpReplace) // .... string replace // ...... non-global search // ........ empty string replace // ........ non-empty string replace (with $-expansion) // ...... global search // ........ no need to circumvent last match info override // ........ need to circument last match info override // .... function replace // ...... global search // ...... non-global search // .. string search // .... special case that replaces with one single character // ...... function replace // ...... string replace (with $-expansion) if ( ! IS_NULL_OR_UNDEFINED ( search ) ) { var replacer = search [ replaceSymbol ] ; if ( ! IS_UNDEFINED ( replacer ) ) { return % _Call ( replacer , search , this , replace ) ; } } var subject = TO_STRING ( this ) ; search = TO_STRING ( search ) ; if ( search . length == 1 && subject . length > 0xFF && IS_STRING ( replace ) && % StringIndexOf ( replace , '$' , 0 ) < 0 ) { // Searching by traversing a cons string tree and replace with cons of // slices works only when the replaced string is a single character, being // replaced by a simple string and only pays off for long strings. return % StringReplaceOneCharWithString ( subject , search , replace ) ; } var start = % StringIndexOf ( subject , search , 0 ) ; if ( start < 0 ) return subject ; var end = start + search . length ; var result = % _SubString ( subject , 0 , start ) ; // Compute the string to replace with. if ( IS_CALLABLE ( replace ) ) { result += replace ( search , start , subject ) ; } else { reusableMatchInfo [ CAPTURE0 ] = start ; reusableMatchInfo [ CAPTURE1 ] = end ; result = ExpandReplacement ( TO_STRING ( replace ) , subject , reusableMatchInfo , result ) ; } return result + % _SubString ( subject , end , subject . length ) ; }
ES6, section 21.1.3.14
ES6 section 21 . 1 . 3 . 14