whole_func_string: function replaceSim (array, index, removeCount, insert) {
          var add = insert ? insert.length : 0,
              length = array.length,
              pos = fixArrayIndex(array, index),
              remove,
              tailOldPos,
              tailNewPos,
              tailCount,
              lengthAfterRemove,
              i;
  
          // we try to use Array.push when we can for efficiency...
          if (pos === length) {
              if (add) {
                  array.push.apply(array, insert);
              }
          } else {
              remove = Math.min(removeCount, length - pos);
              tailOldPos = pos + remove;
              tailNewPos = tailOldPos + add - remove;
              tailCount = length - tailOldPos;
              lengthAfterRemove = length - remove;
  
              if (tailNewPos < tailOldPos) { // case A
                  for (i = 0; i < tailCount; ++i) {
                      array[tailNewPos+i] = array[tailOldPos+i];
                  }
              } else if (tailNewPos > tailOldPos) { // case B
                  for (i = tailCount; i--; ) {
                      array[tailNewPos+i] = array[tailOldPos+i];
                  }
              } // else, add == remove (nothing to do)
  
              if (add && pos === lengthAfterRemove) {
                  array.length = lengthAfterRemove; // truncate array
                  array.push.apply(array, insert);
              } else {
                  array.length = lengthAfterRemove + add; // reserves space
                  for (i = 0; i < add; ++i) {
                      array[pos+i] = insert[i];
                  }
              }
          }
  
          return array;
      }
func_code_string: function replaceSim (array, index, removeCount, insert) {
          var add = insert ? insert.length : 0,
              length = array.length,
              pos = fixArrayIndex(array, index),
              remove,
              tailOldPos,
              tailNewPos,
              tailCount,
              lengthAfterRemove,
              i;
  
          // we try to use Array.push when we can for efficiency...
          if (pos === length) {
              if (add) {
                  array.push.apply(array, insert);
              }
          } else {
              remove = Math.min(removeCount, length - pos);
              tailOldPos = pos + remove;
              tailNewPos = tailOldPos + add - remove;
              tailCount = length - tailOldPos;
              lengthAfterRemove = length - remove;
  
              if (tailNewPos < tailOldPos) { // case A
                  for (i = 0; i < tailCount; ++i) {
                      array[tailNewPos+i] = array[tailOldPos+i];
                  }
              } else if (tailNewPos > tailOldPos) { // case B
                  for (i = tailCount; i--; ) {
                      array[tailNewPos+i] = array[tailOldPos+i];
                  }
              } // else, add == remove (nothing to do)
  
              if (add && pos === lengthAfterRemove) {
                  array.length = lengthAfterRemove; // truncate array
                  array.push.apply(array, insert);
              } else {
                  array.length = lengthAfterRemove + add; // reserves space
                  for (i = 0; i < add; ++i) {
                      array[pos+i] = insert[i];
                  }
              }
          }
  
          return array;
      }
func_documentation_string: /*
  Does the same work as splice, but with a slightly more convenient signature. The splice
  method has bugs in IE8, so this is the implementation we use on that platform.
  
  The rippling of items in the array can be tricky. Consider two use cases:
  
  index=2
  removeCount=2
  /=====\
  +---+---+---+---+---+---+---+---+
  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
  +---+---+---+---+---+---+---+---+
  /  \/  \/  \/  \
  /   /\  /\  /\   \
  /   /  \/  \/  \   +--------------------------+
  /   /   /\  /\   +--------------------------+   \
  /   /   /  \/  +--------------------------+   \   \
  /   /   /   /+--------------------------+   \   \   \
  /   /   /   /                             \   \   \   \
  v   v   v   v                               v   v   v   v
  +---+---+---+---+---+---+       +---+---+---+---+---+---+---+---+---+
  | 0 | 1 | 4 | 5 | 6 | 7 |       | 0 | 1 | a | b | c | 4 | 5 | 6 | 7 |
  +---+---+---+---+---+---+       +---+---+---+---+---+---+---+---+---+
  A                               B        \=========/
  insert=[a,b,c]
  
  In case A, it is obvious that copying of [4,5,6,7] must be left-to-right so
  that we don't end up with [0,1,6,7,6,7]. In case B, we have the opposite; we
  must go right-to-left or else we would end up with [0,1,a,b,c,4,4,4,4].