PageRenderTime 737ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/test/mjsunit/array-slice.js

http://github.com/v8/v8
JavaScript | 328 lines | 216 code | 56 blank | 56 comment | 12 complexity | 227e84c54399de25924a5ce421003d53 MD5 | raw file
Possible License(s): BSD-3-Clause, CC0-1.0, Apache-2.0
  1. // Copyright 2010 the V8 project authors. All rights reserved.
  2. // Redistribution and use in source and binary forms, with or without
  3. // modification, are permitted provided that the following conditions are
  4. // met:
  5. //
  6. // * Redistributions of source code must retain the above copyright
  7. // notice, this list of conditions and the following disclaimer.
  8. // * Redistributions in binary form must reproduce the above
  9. // copyright notice, this list of conditions and the following
  10. // disclaimer in the documentation and/or other materials provided
  11. // with the distribution.
  12. // * Neither the name of Google Inc. nor the names of its
  13. // contributors may be used to endorse or promote products derived
  14. // from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. // Flags: --allow-natives-syntax
  28. // Check that slicing array of holes keeps it as array of holes
  29. (function() {
  30. var array = new Array(10);
  31. for (var i = 0; i < 7; i++) {
  32. var sliced = array.slice();
  33. assertEquals(array.length, sliced.length);
  34. assertFalse(0 in sliced);
  35. }
  36. })();
  37. // Check various variants of empty array's slicing.
  38. (function() {
  39. for (var i = 0; i < 7; i++) {
  40. assertEquals([], [].slice(0, 0));
  41. assertEquals([], [].slice(1, 0));
  42. assertEquals([], [].slice(0, 1));
  43. assertEquals([], [].slice(-1, 0));
  44. }
  45. })();
  46. // Check various forms of arguments omission.
  47. (function() {
  48. var array = new Array(7);
  49. for (var i = 0; i < 7; i++) {
  50. assertEquals(array, array.slice());
  51. assertEquals(array, array.slice(0));
  52. assertEquals(array, array.slice(undefined));
  53. assertEquals(array, array.slice("foobar"));
  54. assertEquals(array, array.slice(undefined, undefined));
  55. }
  56. })();
  57. // Check variants of negatives and positive indices.
  58. (function() {
  59. var array = new Array(7);
  60. for (var i = 0; i < 7; i++) {
  61. assertEquals(7, array.slice(-100).length);
  62. assertEquals(3, array.slice(-3).length);
  63. assertEquals(3, array.slice(4).length);
  64. assertEquals(1, array.slice(6).length);
  65. assertEquals(0, array.slice(7).length);
  66. assertEquals(0, array.slice(8).length);
  67. assertEquals(0, array.slice(100).length);
  68. assertEquals(0, array.slice(0, -100).length);
  69. assertEquals(4, array.slice(0, -3).length);
  70. assertEquals(4, array.slice(0, 4).length);
  71. assertEquals(6, array.slice(0, 6).length);
  72. assertEquals(7, array.slice(0, 7).length);
  73. assertEquals(7, array.slice(0, 8).length);
  74. assertEquals(7, array.slice(0, 100).length);
  75. // Some exotic cases.
  76. obj = { toString: function() { throw 'Exception'; } };
  77. // More than 2 arguments:
  78. assertEquals(7, array.slice(0, 7, obj, null, undefined).length);
  79. // Custom conversion:
  80. assertEquals(1, array.slice({valueOf: function() { return 1; }},
  81. {toString: function() { return 2; }}).length);
  82. // Throwing an exception in conversion:
  83. try {
  84. assertEquals(7, array.slice(0, obj).length);
  85. throw 'Should have thrown';
  86. } catch (e) {
  87. assertEquals('Exception', e);
  88. }
  89. }
  90. })();
  91. // Nasty: modify the array in ToInteger.
  92. (function() {
  93. var array = [];
  94. var expected = []
  95. bad_guy = { valueOf: function() { array.push(array.length); return -1; } };
  96. for (var i = 0; i < 13; i++) {
  97. var sliced = array.slice(bad_guy);
  98. expected.push(i);
  99. assertEquals(expected, array);
  100. // According to the spec (15.4.4.10), length is calculated before
  101. // performing ToInteger on arguments.
  102. if (i == 0) {
  103. assertEquals([], sliced); // Length was 0, nothing to get.
  104. } else {
  105. // Actually out of array [0..i] we get [i - 1] as length is i.
  106. assertEquals([i - 1], sliced);
  107. }
  108. }
  109. })();
  110. // Now check the case with array of holes and some elements on prototype.
  111. // Note: that is important that this test runs before the next one
  112. // as the next one tampers Array.prototype.
  113. (function() {
  114. var len = 9;
  115. var array = new Array(len);
  116. var at3 = "@3";
  117. var at7 = "@7";
  118. for (var i = 0; i < 7; i++) {
  119. var array_proto = [];
  120. array_proto[3] = at3;
  121. array_proto[7] = at7;
  122. array.__proto__ = array_proto;
  123. assertEquals(len, array.length);
  124. for (var i = 0; i < array.length; i++) {
  125. assertEquals(array[i], array_proto[i]);
  126. }
  127. var sliced = array.slice();
  128. assertEquals(len, sliced.length);
  129. assertTrue(delete array_proto[3]);
  130. assertTrue(delete array_proto[7]);
  131. // Note that slice copies values from prototype into the array.
  132. assertEquals(array[3], undefined);
  133. assertFalse(array.hasOwnProperty(3));
  134. assertEquals(sliced[3], at3);
  135. assertTrue(sliced.hasOwnProperty(3));
  136. assertEquals(array[7], undefined);
  137. assertFalse(array.hasOwnProperty(7));
  138. assertEquals(sliced[7], at7);
  139. assertTrue(sliced.hasOwnProperty(7));
  140. // ... but keeps the rest as holes:
  141. array_proto[5] = "@5";
  142. assertEquals(array[5], array_proto[5]);
  143. assertFalse(array.hasOwnProperty(5));
  144. }
  145. })();
  146. // Now check the case with array of holes and some elements on prototype.
  147. (function() {
  148. var len = 9;
  149. var array = new Array(len);
  150. var at3 = "@3";
  151. var at7 = "@7";
  152. for (var i = 0; i < 7; i++) {
  153. Array.prototype[3] = at3;
  154. Array.prototype[7] = at7;
  155. assertEquals(len, array.length);
  156. for (var i = 0; i < array.length; i++) {
  157. assertEquals(array[i], Array.prototype[i]);
  158. }
  159. var sliced = array.slice();
  160. assertEquals(len, sliced.length);
  161. assertTrue(delete Array.prototype[3]);
  162. assertTrue(delete Array.prototype[7]);
  163. // Note that slice copies values from prototype into the array.
  164. assertEquals(array[3], undefined);
  165. assertFalse(array.hasOwnProperty(3));
  166. assertEquals(sliced[3], at3);
  167. assertTrue(sliced.hasOwnProperty(3));
  168. assertEquals(array[7], undefined);
  169. assertFalse(array.hasOwnProperty(7));
  170. assertEquals(sliced[7], at7);
  171. assertTrue(sliced.hasOwnProperty(7));
  172. // ... but keeps the rest as holes:
  173. Array.prototype[5] = "@5";
  174. assertEquals(array[5], Array.prototype[5]);
  175. assertFalse(array.hasOwnProperty(5));
  176. assertEquals(sliced[5], Array.prototype[5]);
  177. assertFalse(sliced.hasOwnProperty(5));
  178. assertTrue(delete Array.prototype[5]);
  179. }
  180. })();
  181. // Check slicing on arguments object.
  182. (function() {
  183. function func(expected, a0, a1, a2) {
  184. let result = Array.prototype.slice.call(arguments, 1);
  185. %HeapObjectVerify(result);
  186. %HeapObjectVerify(arguments);
  187. assertEquals(expected, result);
  188. }
  189. func([]);
  190. func(['a'], 'a');
  191. func(['a', 1], 'a', 1);
  192. func(['a', 1, 2, 3, 4, 5], 'a', 1, 2, 3, 4, 5);
  193. func(['a', 1, undefined], 'a', 1, undefined);
  194. func(['a', 1, undefined, void(0)], 'a', 1, undefined, void(0));
  195. })();
  196. // Check slicing on arguments object when missing arguments get assigined.
  197. (function() {
  198. function func(x, y) {
  199. assertEquals(1, arguments.length);
  200. assertEquals(undefined, y);
  201. y = 239;
  202. assertEquals(1, arguments.length); // arguments length is the same.
  203. let result = Array.prototype.slice.call(arguments, 0);
  204. %HeapObjectVerify(result);
  205. %HeapObjectVerify(arguments);
  206. assertEquals([x], result);
  207. }
  208. func('a');
  209. })();
  210. // Check slicing on arguments object when length property has been set.
  211. (function() {
  212. function func(x, y) {
  213. assertEquals(1, arguments.length);
  214. arguments.length = 7;
  215. let result = Array.prototype.slice.call(arguments, 0);
  216. assertEquals([x,,,,,,,], result);
  217. %HeapObjectVerify(result);
  218. %HeapObjectVerify(arguments);
  219. }
  220. func('a');
  221. })();
  222. // Check slicing on arguments object when length property has been set to
  223. // some strange value.
  224. (function() {
  225. function func(x, y) {
  226. assertEquals(1, arguments.length);
  227. arguments.length = 'foobar';
  228. let result = Array.prototype.slice.call(arguments, 0);
  229. assertEquals([], result);
  230. %HeapObjectVerify(result);
  231. %HeapObjectVerify(arguments);
  232. }
  233. func('a');
  234. })();
  235. // Check slicing on arguments object when extra argument has been added
  236. // via indexed assignment.
  237. (function() {
  238. function func(x, y) {
  239. assertEquals(1, arguments.length);
  240. arguments[3] = 239;
  241. let result = Array.prototype.slice.call(arguments, 0);
  242. assertEquals([x], result);
  243. %HeapObjectVerify(result);
  244. %HeapObjectVerify(arguments);
  245. }
  246. func('a');
  247. })();
  248. // Check slicing on arguments object when argument has been deleted by index.
  249. (function() {
  250. function func(x, y, z) {
  251. assertEquals(3, arguments.length);
  252. delete arguments[1];
  253. let result = Array.prototype.slice.call(arguments, 0);
  254. assertEquals([x,,z], result);
  255. %HeapObjectVerify(result);
  256. %HeapObjectVerify(arguments);
  257. }
  258. func('a', 'b', 'c');
  259. })();
  260. // Check slicing of holey objects with elements in the prototype
  261. (function() {
  262. function f() {
  263. delete arguments[1];
  264. arguments.__proto__[1] = 5;
  265. var result = Array.prototype.slice.call(arguments);
  266. delete arguments.__proto__[1];
  267. assertEquals([1,5,3], result);
  268. %HeapObjectVerify(result);
  269. %HeapObjectVerify(arguments);
  270. }
  271. f(1,2,3);
  272. })();