1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Based on Mozilla Array.of() tests at http://dxr.mozilla.org/mozilla-central/source/js/src/jit-test/tests/collections 6 7// Flags: --harmony-arrays 8 9 10 11// Array.of makes real arrays. 12 13function check(a) { 14 assertEquals(Object.getPrototypeOf(a), Array.prototype); 15 assertEquals(Array.isArray(a), true); 16 a[9] = 9; 17 assertEquals(a.length, 10); 18} 19 20 21check(Array.of()); 22check(Array.of(0)); 23check(Array.of(0, 1, 2)); 24var f = Array.of; 25check(f()); 26 27 28// Array.of basics 29 30var a = Array.of(); 31 32assertEquals(a.length, 0); 33a = Array.of(undefined, null, 3.14, []); 34assertEquals(a, [undefined, null, 3.14, []]); 35a = []; 36for (var i = 0; i < 1000; i++) 37 a[i] = i; 38assertEquals(Array.of.apply(null, a), a); 39 40 41// Array.of does not leave holes 42 43assertEquals(Array.of(undefined), [undefined]); 44assertEquals(Array.of(undefined, undefined), [undefined, undefined]); 45assertEquals(Array.of.apply(null, [,,undefined]), [undefined, undefined, undefined]); 46assertEquals(Array.of.apply(null, Array(4)), [undefined, undefined, undefined, undefined]); 47 48 49// Array.of can be transplanted to other classes. 50 51var hits = 0; 52function Bag() { 53 hits++; 54} 55Bag.of = Array.of; 56 57hits = 0; 58var actual = Bag.of("zero", "one"); 59assertEquals(hits, 1); 60 61hits = 0; 62var expected = new Bag; 63expected[0] = "zero"; 64expected[1] = "one"; 65expected.length = 2; 66assertEquals(areSame(actual, expected), true); 67 68hits = 0; 69actual = Array.of.call(Bag, "zero", "one"); 70assertEquals(hits, 1); 71assertEquals(areSame(actual, expected), true); 72 73function areSame(object, array) { 74 var result = object.length == array.length; 75 for (var i = 0; i < object.length; i++) { 76 result = result && object[i] == array[i]; 77 } 78 return result; 79} 80 81 82// Array.of does not trigger prototype setters. 83// (It defines elements rather than assigning to them.) 84 85var status = "pass"; 86Object.defineProperty(Array.prototype, "0", {set: function(v) {status = "FAIL 1"}}); 87assertEquals(Array.of(1)[0], 1); 88assertEquals(status, "pass"); 89 90Object.defineProperty(Bag.prototype, "0", {set: function(v) {status = "FAIL 2"}}); 91assertEquals(Bag.of(1)[0], 1); 92assertEquals(status, "pass"); 93 94 95// Array.of passes the number of arguments to the constructor it calls. 96 97var hits = 0; 98 99function Herd(n) { 100 assertEquals(arguments.length, 1); 101 assertEquals(n, 5); 102 hits++; 103} 104 105Herd.of = Array.of; 106Herd.of("sheep", "cattle", "elephants", "whales", "seals"); 107assertEquals(hits, 1); 108 109 110// Array.of calls a "length" setter if one is present. 111 112var hits = 0; 113var lastObj = null, lastVal = undefined; 114function setter(v) { 115 hits++; 116 lastObj = this; 117 lastVal = v; 118} 119 120// when the setter is on the new object 121function Pack() { 122 Object.defineProperty(this, "length", {set: setter}); 123} 124Pack.of = Array.of; 125var pack = Pack.of("wolves", "cards", "cigarettes", "lies"); 126assertEquals(lastObj, pack); 127assertEquals(lastVal, 4); 128 129// when the setter is on the new object's prototype 130function Bevy() {} 131Object.defineProperty(Bevy.prototype, "length", {set: setter}); 132Bevy.of = Array.of; 133var bevy = Bevy.of("quail"); 134assertEquals(lastObj, bevy); 135assertEquals(lastVal, 1); 136 137 138// Array.of does a strict assignment to the new object's .length. 139// The assignment is strict even if the code we're calling from is not strict. 140 141function Empty() {} 142Empty.of = Array.of; 143Object.defineProperty(Empty.prototype, "length", {get: function() { return 0; }}); 144 145var nothing = new Empty; 146nothing.length = 2; // no exception; this is not a strict mode assignment 147 148assertThrows(function() { Empty.of(); }, TypeError); 149 150 151// Check superficial features of Array.of. 152 153var desc = Object.getOwnPropertyDescriptor(Array, "of"); 154 155assertEquals(desc.configurable, true); 156assertEquals(desc.enumerable, false); 157assertEquals(desc.writable, true); 158assertEquals(Array.of.length, 0); 159assertThrows(function() { new Array.of() }, TypeError); // not a constructor 160 161// When the this-value passed in is not a constructor, the result is an array. 162[undefined, null, false, "cow"].forEach(function(val) { 163 assertEquals(Array.isArray(Array.of(val)), true); 164}); 165