text: // Copyright 2008 the V8 project authors. All rights reserved.
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  //
  //     * Redistributions of source code must retain the above copyright
  //       notice, this list of conditions and the following disclaimer.
  //     * Redistributions in binary form must reproduce the above
  //       copyright notice, this list of conditions and the following
  //       disclaimer in the documentation and/or other materials provided
  //       with the distribution.
  //     * Neither the name of Google Inc. nor the names of its
  //       contributors may be used to endorse or promote products derived
  //       from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  /**
   * @fileoverview Test splice, shift, unshift, slice and join on small
   * and large arrays.  Some of these methods are specified such that they
   * should work on other objects too, so we test that too.
   */
  
  var LARGE = 40000000;
  var VERYLARGE = 4000000000;
  
  // Nicer for firefox 1.5.  Unless you uncomment the following two lines,
  // smjs will appear to hang on this file.
  //var LARGE = 40000;
  //var VERYLARGE = 40000;
  
  var fourhundredth = LARGE/400;
  
  function PseudoArray() {
  };
  
  for (var use_real_arrays = 0; use_real_arrays <= 1; use_real_arrays++) {
    var poses = [0, 140, 40000, VERYLARGE];
    var the_prototype;
    var new_function;
    var push_function;
    var concat_function;
    var slice_function;
    var splice_function;
    var splice_function_2;
    var unshift_function;
    var unshift_function_2;
    var shift_function;
    if (use_real_arrays) {
      new_function = function(length) {
        return new Array(length);
      };
      the_prototype = Array.prototype;
      push_function = function(array, elt) {
        return array.push(elt);
      };
      concat_function = function(array, other) {
        return array.concat(other);
      };
      slice_function = function(array, start, len) {
        return array.slice(start, len);
      };
      splice_function = function(array, start, len) {
        return array.splice(start, len);
      };
      splice_function_2 = function(array, start, len, elt) {
        return array.splice(start, len, elt);
      };
      unshift_function = function(array, elt) {
        return array.unshift(elt);
      };
      unshift_function_2 = function(array, elt1, elt2) {
        return array.unshift(elt1, elt2);
      };
      shift_function = function(array) {
        return array.shift();
      };
    } else {
      // Don't run largest size on non-arrays or we'll be here for ever.
      poses.pop();
      new_function = function(length) {
        var obj = new PseudoArray();
        obj.length = length;
        return obj;
      };
      the_prototype = PseudoArray.prototype;
      push_function = function(array, elt) {
        array[array.length] = elt;
        array.length++;
      };
      concat_function = function(array, other) {
        return Array.prototype.concat.call(array, other);
      };
      slice_function = function(array, start, len) {
        return Array.prototype.slice.call(array, start, len);
      };
      splice_function = function(array, start, len) {
        return Array.prototype.splice.call(array, start, len);
      };
      splice_function_2 = function(array, start, len, elt) {
        return Array.prototype.splice.call(array, start, len, elt);
      };
      unshift_function = function(array, elt) {
        return Array.prototype.unshift.call(array, elt);
      };
      unshift_function_2 = function(array, elt1, elt2) {
        return Array.prototype.unshift.call(array, elt1, elt2);
      };
      shift_function = function(array) {
        return Array.prototype.shift.call(array);
      };
    }
  
    for (var pos_pos = 0; pos_pos < poses.length; pos_pos++) {
      var pos = poses[pos_pos];
      if (pos > 100) {
        var a = new_function(pos);
        assertEquals(pos, a.length);
        push_function(a, 'foo');
        assertEquals(pos + 1, a.length);
        var b = ['bar'];
        // Delete a huge number of holes.
        var c = splice_function(a, 10, pos - 20);
        assertEquals(pos - 20, c.length);
        assertEquals(21, a.length);
      }
  
      // Add a numeric property to the prototype of the array class.  This
      // allows us to test some borderline stuff relative to the standard.
      the_prototype["" + (pos + 1)] = 'baz';
  
      if (use_real_arrays) {
        // It seems quite clear from ECMAScript spec 15.4.4.5.  Just call Get on
        // every integer in the range.
        // IE, Safari get this right.
        // FF, Opera get this wrong.
        var a = ['zero', ,'two'];
        if (pos == 0) {
          assertEquals("zero,baz,two", a.join(","));
        }
  
        // Concat only applies to real arrays, unlike most of the other methods.
        var a = new_function(pos);
        push_function(a, "con");
        assertEquals("con", a[pos]);
        assertEquals(pos + 1, a.length);
        var b = new_function(0);
        push_function(b, "cat");
        assertEquals("cat", b[0]);
        var ab = concat_function(a, b);
        assertEquals("con", ab[pos]);
        assertEquals(pos + 2, ab.length);
        assertEquals("cat", ab[pos + 1]);
        var ba = concat_function(b, a);
        assertEquals("con", ba[pos + 1]);
        assertEquals(pos + 2, ba.length);
        assertEquals("cat", ba[0]);
  
        // Join with '' as separator.
        var join = a.join('');
        assertEquals("con", join);
        join = b.join('');
        assertEquals("cat", join);
        join = ab.join('');
        assertEquals("concat", join);
        join = ba.join('');
        assertEquals("catcon", join);
  
        var sparse = [];
        sparse[pos + 1000] = 'is ';
        sparse[pos + 271828] = 'time ';
        sparse[pos + 31415] = 'the ';
        sparse[pos + 12260199] = 'all ';
        sparse[-1] = 'foo';
        sparse[pos + 22591927] = 'good ';
        sparse[pos + 1618033] = 'for ';
        sparse[pos + 91] = ': Now ';
        sparse[pos + 86720199] = 'men.';
        sparse.hest = 'fisk';
  
        assertEquals("baz: Now is the time for all good men.", sparse.join(''));
      }
  
      a = new_function(pos);
      push_function(a, 'zero');
      push_function(a, void 0);
      push_function(a, 'two');
  
      // Splice works differently from join.
      // IE, Safari get this wrong.
      // FF, Opera get this right.
      // 15.4.4.12 line 24 says the object itself has to have the property...
      var zero = splice_function(a, pos, 1);
      assertEquals("undefined", typeof(a[pos]));
      assertEquals("two", a[pos+1], "pos1:" + pos);
      assertEquals(pos + 2, a.length, "a length");
      assertEquals(1, zero.length, "zero length");
      assertEquals("zero", zero[0]);
  
      // 15.4.4.12 line 41 says the object itself has to have the property...
      a = new_function(pos);
      push_function(a, 'zero');
      push_function(a, void 0);
      push_function(a, 'two');
      var nothing = splice_function_2(a, pos, 0, 'minus1');
      assertEquals("minus1", a[pos]);
      assertEquals("zero", a[pos+1]);
      assertEquals("undefined", typeof(a[pos+2]), "toot!");
      assertEquals("two", a[pos+3], "pos3");
      assertEquals(pos + 4, a.length);
      assertEquals(1, zero.length);
      assertEquals("zero", zero[0]);
  
      // 15.4.4.12 line 10 says the object itself has to have the property...
      a = new_function(pos);
      push_function(a, 'zero');
      push_function(a, void 0);
      push_function(a, 'two');
      var one = splice_function(a, pos + 1, 1);
      assertEquals("", one.join(","));
      assertEquals(pos + 2, a.length);
      assertEquals("zero", a[pos]);
      assertEquals("two", a[pos+1]);
  
      // Set things back to the way they were.
      the_prototype[pos + 1] = undefined;
  
      // Unshift.
      var a = new_function(pos);
      push_function(a, "foo");
      assertEquals("foo", a[pos]);
      assertEquals(pos + 1, a.length);
      unshift_function(a, "bar");
      assertEquals("foo", a[pos+1]);
      assertEquals(pos + 2, a.length);
      assertEquals("bar", a[0]);
      unshift_function_2(a, "baz", "boo");
      assertEquals("foo", a[pos+3]);
      assertEquals(pos + 4, a.length);
      assertEquals("baz", a[0]);
      assertEquals("boo", a[1]);
      assertEquals("bar", a[2]);
  
      // Shift.
      var baz = shift_function(a);
      assertEquals("baz", baz);
      assertEquals("boo", a[0]);
      assertEquals(pos + 3, a.length);
      assertEquals("foo", a[pos + 2]);
  
      // Slice.
      var bar = slice_function(a, 1, 0);  // don't throw an exception please.
      bar = slice_function(a, 1, 2);
      assertEquals("bar", bar[0]);
      assertEquals(1, bar.length);
      assertEquals("bar", a[1]);
  
    }
  }
  
  // Lets see if performance is reasonable.
  
  var a = new Array(LARGE + 10);
  for (var i = 0; i < a.length; i += 1000) {
    a[i] = i;
  }
  
  // Take something near the end of the array.
  for (var i = 0; i < 100; i++) {
    var top = a.splice(LARGE, 5);
    assertEquals(5, top.length);
    assertEquals(LARGE, top[0]);
    assertEquals("undefined", typeof(top[1]));
    assertEquals(LARGE + 5, a.length);
    a.splice(LARGE, 0, LARGE);
    a.length = LARGE + 10;
  }
  
  var a = new Array(LARGE + 10);
  for (var i = 0; i < a.length; i += fourhundredth) {
    a[i] = i;
  }
  
  // Take something near the middle of the array.
  for (var i = 0; i < 10; i++) {
    var top = a.splice(LARGE >> 1, 5);
    assertEquals(5, top.length);
    assertEquals(LARGE >> 1, top[0]);
    assertEquals("undefined", typeof(top[1]));
    assertEquals(LARGE + 5, a.length);
    a.splice(LARGE >> 1, 0, LARGE >> 1, void 0, void 0, void 0, void 0);
  }
  
  
  // Test http://b/issue?id=1202711
  arr = [0];
  arr.length = 2;
  Array.prototype[1] = 1;
  assertEquals(1, arr.pop());
  assertEquals(0, arr.pop());
  Array.prototype[1] = undefined;
  
  
  