OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 (function(global, utils, extrasUtils) { | 5 (function(global, utils, extrasUtils) { |
6 | 6 |
7 "use strict"; | 7 "use strict"; |
8 | 8 |
9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
10 | 10 |
11 // ------------------------------------------------------------------- | 11 // ------------------------------------------------------------------- |
12 // Imports | 12 // Imports |
13 | 13 |
14 var AddIndexedProperty; | 14 var AddIndexedProperty; |
15 var FLAG_harmony_tolength; | 15 var FLAG_harmony_tolength; |
| 16 var FLAG_harmony_species; |
16 var GetIterator; | 17 var GetIterator; |
17 var GetMethod; | 18 var GetMethod; |
18 var GlobalArray = global.Array; | 19 var GlobalArray = global.Array; |
19 var InternalArray = utils.InternalArray; | 20 var InternalArray = utils.InternalArray; |
20 var InternalPackedArray = utils.InternalPackedArray; | 21 var InternalPackedArray = utils.InternalPackedArray; |
21 var MakeTypeError; | 22 var MakeTypeError; |
22 var MaxSimple; | 23 var MaxSimple; |
23 var MinSimple; | 24 var MinSimple; |
24 var ObjectDefineProperty; | 25 var ObjectDefineProperty; |
25 var ObjectHasOwnProperty; | 26 var ObjectHasOwnProperty; |
(...skipping 15 matching lines...) Expand all Loading... |
41 ObjectDefineProperty = from.ObjectDefineProperty; | 42 ObjectDefineProperty = from.ObjectDefineProperty; |
42 ObjectHasOwnProperty = from.ObjectHasOwnProperty; | 43 ObjectHasOwnProperty = from.ObjectHasOwnProperty; |
43 ObserveBeginPerformSplice = from.ObserveBeginPerformSplice; | 44 ObserveBeginPerformSplice = from.ObserveBeginPerformSplice; |
44 ObserveEndPerformSplice = from.ObserveEndPerformSplice; | 45 ObserveEndPerformSplice = from.ObserveEndPerformSplice; |
45 ObserveEnqueueSpliceRecord = from.ObserveEnqueueSpliceRecord; | 46 ObserveEnqueueSpliceRecord = from.ObserveEnqueueSpliceRecord; |
46 SameValueZero = from.SameValueZero; | 47 SameValueZero = from.SameValueZero; |
47 }); | 48 }); |
48 | 49 |
49 utils.ImportFromExperimental(function(from) { | 50 utils.ImportFromExperimental(function(from) { |
50 FLAG_harmony_tolength = from.FLAG_harmony_tolength; | 51 FLAG_harmony_tolength = from.FLAG_harmony_tolength; |
| 52 FLAG_harmony_species = from.FLAG_harmony_species; |
51 }); | 53 }); |
52 | 54 |
53 // ------------------------------------------------------------------- | 55 // ------------------------------------------------------------------- |
54 | 56 |
| 57 |
| 58 function ArraySpeciesCreate(array, length) { |
| 59 var constructor; |
| 60 if (FLAG_harmony_species) { |
| 61 constructor = %ArraySpeciesConstructor(array); |
| 62 } else { |
| 63 constructor = GlobalArray; |
| 64 } |
| 65 return new constructor(length); |
| 66 } |
| 67 |
| 68 |
| 69 function DefineIndexedProperty(array, i, value) { |
| 70 if (FLAG_harmony_species) { |
| 71 var result = ObjectDefineProperty(array, i, { |
| 72 value: value, writable: true, configurable: true, enumerable: true |
| 73 }); |
| 74 if (!result) throw MakeTypeError(kStrictCannotAssign, i); |
| 75 } else { |
| 76 AddIndexedProperty(array, i, value); |
| 77 } |
| 78 } |
| 79 |
| 80 |
55 // Global list of arrays visited during toString, toLocaleString and | 81 // Global list of arrays visited during toString, toLocaleString and |
56 // join invocations. | 82 // join invocations. |
57 var visited_arrays = new InternalArray(); | 83 var visited_arrays = new InternalArray(); |
58 | 84 |
59 | 85 |
60 // Gets a sorted array of array keys. Useful for operations on sparse | 86 // Gets a sorted array of array keys. Useful for operations on sparse |
61 // arrays. Dupes have not been removed. | 87 // arrays. Dupes have not been removed. |
62 function GetSortedArrayKeys(array, indices) { | 88 function GetSortedArrayKeys(array, indices) { |
63 var keys = new InternalArray(); | 89 var keys = new InternalArray(); |
64 if (IS_NUMBER(indices)) { | 90 if (IS_NUMBER(indices)) { |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 // This function implements the optimized splice implementation that can use | 270 // This function implements the optimized splice implementation that can use |
245 // special array operations to handle sparse arrays in a sensible fashion. | 271 // special array operations to handle sparse arrays in a sensible fashion. |
246 function SparseSlice(array, start_i, del_count, len, deleted_elements) { | 272 function SparseSlice(array, start_i, del_count, len, deleted_elements) { |
247 // Move deleted elements to a new array (the return value from splice). | 273 // Move deleted elements to a new array (the return value from splice). |
248 var indices = %GetArrayKeys(array, start_i + del_count); | 274 var indices = %GetArrayKeys(array, start_i + del_count); |
249 if (IS_NUMBER(indices)) { | 275 if (IS_NUMBER(indices)) { |
250 var limit = indices; | 276 var limit = indices; |
251 for (var i = start_i; i < limit; ++i) { | 277 for (var i = start_i; i < limit; ++i) { |
252 var current = array[i]; | 278 var current = array[i]; |
253 if (!IS_UNDEFINED(current) || i in array) { | 279 if (!IS_UNDEFINED(current) || i in array) { |
254 AddIndexedProperty(deleted_elements, i - start_i, current); | 280 DefineIndexedProperty(deleted_elements, i - start_i, current); |
255 } | 281 } |
256 } | 282 } |
257 } else { | 283 } else { |
258 var length = indices.length; | 284 var length = indices.length; |
259 for (var k = 0; k < length; ++k) { | 285 for (var k = 0; k < length; ++k) { |
260 var key = indices[k]; | 286 var key = indices[k]; |
261 if (!IS_UNDEFINED(key)) { | 287 if (!IS_UNDEFINED(key)) { |
262 if (key >= start_i) { | 288 if (key >= start_i) { |
263 var current = array[key]; | 289 var current = array[key]; |
264 if (!IS_UNDEFINED(current) || key in array) { | 290 if (!IS_UNDEFINED(current) || key in array) { |
265 AddIndexedProperty(deleted_elements, key - start_i, current); | 291 DefineIndexedProperty(deleted_elements, key - start_i, current); |
266 } | 292 } |
267 } | 293 } |
268 } | 294 } |
269 } | 295 } |
270 } | 296 } |
271 } | 297 } |
272 | 298 |
273 | 299 |
274 // This function implements the optimized splice implementation that can use | 300 // This function implements the optimized splice implementation that can use |
275 // special array operations to handle sparse arrays in a sensible fashion. | 301 // special array operations to handle sparse arrays in a sensible fashion. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 | 361 |
336 // This is part of the old simple-minded splice. We are using it either | 362 // This is part of the old simple-minded splice. We are using it either |
337 // because the receiver is not an array (so we have no choice) or because we | 363 // because the receiver is not an array (so we have no choice) or because we |
338 // know we are not deleting or moving a lot of elements. | 364 // know we are not deleting or moving a lot of elements. |
339 function SimpleSlice(array, start_i, del_count, len, deleted_elements) { | 365 function SimpleSlice(array, start_i, del_count, len, deleted_elements) { |
340 var is_array = IS_ARRAY(array); | 366 var is_array = IS_ARRAY(array); |
341 for (var i = 0; i < del_count; i++) { | 367 for (var i = 0; i < del_count; i++) { |
342 var index = start_i + i; | 368 var index = start_i + i; |
343 if (HAS_INDEX(array, index, is_array)) { | 369 if (HAS_INDEX(array, index, is_array)) { |
344 var current = array[index]; | 370 var current = array[index]; |
345 // The spec requires [[DefineOwnProperty]] here, AddIndexedProperty is | 371 DefineIndexedProperty(deleted_elements, i, current); |
346 // close enough (in that it ignores the prototype). | |
347 AddIndexedProperty(deleted_elements, i, current); | |
348 } | 372 } |
349 } | 373 } |
350 } | 374 } |
351 | 375 |
352 | 376 |
353 function SimpleMove(array, start_i, del_count, len, num_additional_args) { | 377 function SimpleMove(array, start_i, del_count, len, num_additional_args) { |
354 var is_array = IS_ARRAY(array); | 378 var is_array = IS_ARRAY(array); |
355 if (num_additional_args !== del_count) { | 379 if (num_additional_args !== del_count) { |
356 // Move the existing elements after the elements to be deleted | 380 // Move the existing elements after the elements to be deleted |
357 // to the right position in the resulting array. | 381 // to the right position in the resulting array. |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 if (start_i > len) start_i = len; | 776 if (start_i > len) start_i = len; |
753 } | 777 } |
754 | 778 |
755 if (end_i < 0) { | 779 if (end_i < 0) { |
756 end_i += len; | 780 end_i += len; |
757 if (end_i < 0) end_i = 0; | 781 if (end_i < 0) end_i = 0; |
758 } else { | 782 } else { |
759 if (end_i > len) end_i = len; | 783 if (end_i > len) end_i = len; |
760 } | 784 } |
761 | 785 |
762 var result = []; | 786 var result = ArraySpeciesCreate(array, MaxSimple(end_i - start_i, 0)); |
763 | 787 |
764 if (end_i < start_i) return result; | 788 if (end_i < start_i) return result; |
765 | 789 |
766 if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) { | 790 if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) { |
767 %NormalizeElements(array); | 791 %NormalizeElements(array); |
768 %NormalizeElements(result); | 792 %NormalizeElements(result); |
769 SparseSlice(array, start_i, end_i - start_i, len, result); | 793 SparseSlice(array, start_i, end_i - start_i, len, result); |
770 } else { | 794 } else { |
771 SimpleSlice(array, start_i, end_i - start_i, len, result); | 795 SimpleSlice(array, start_i, end_i - start_i, len, result); |
772 } | 796 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 | 878 |
855 if (%IsObserved(this)) | 879 if (%IsObserved(this)) |
856 return ObservedArraySplice.apply(this, arguments); | 880 return ObservedArraySplice.apply(this, arguments); |
857 | 881 |
858 var num_arguments = %_ArgumentsLength(); | 882 var num_arguments = %_ArgumentsLength(); |
859 var array = TO_OBJECT(this); | 883 var array = TO_OBJECT(this); |
860 var len = TO_LENGTH_OR_UINT32(array.length); | 884 var len = TO_LENGTH_OR_UINT32(array.length); |
861 var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len); | 885 var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len); |
862 var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len, | 886 var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len, |
863 start_i); | 887 start_i); |
864 var deleted_elements = []; | 888 var deleted_elements = ArraySpeciesCreate(array, del_count); |
865 deleted_elements.length = del_count; | 889 deleted_elements.length = del_count; |
866 var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0; | 890 var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0; |
867 | 891 |
868 if (del_count != num_elements_to_add && %object_is_sealed(array)) { | 892 if (del_count != num_elements_to_add && %object_is_sealed(array)) { |
869 throw MakeTypeError(kArrayFunctionsOnSealed); | 893 throw MakeTypeError(kArrayFunctionsOnSealed); |
870 } else if (del_count > 0 && %object_is_frozen(array)) { | 894 } else if (del_count > 0 && %object_is_frozen(array)) { |
871 throw MakeTypeError(kArrayFunctionsOnFrozen); | 895 throw MakeTypeError(kArrayFunctionsOnFrozen); |
872 } | 896 } |
873 | 897 |
874 var changed_elements = del_count; | 898 var changed_elements = del_count; |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1194 | 1218 |
1195 var array = TO_OBJECT(this); | 1219 var array = TO_OBJECT(this); |
1196 var length = TO_LENGTH_OR_UINT32(array.length); | 1220 var length = TO_LENGTH_OR_UINT32(array.length); |
1197 return InnerArraySort(array, length, comparefn); | 1221 return InnerArraySort(array, length, comparefn); |
1198 } | 1222 } |
1199 | 1223 |
1200 | 1224 |
1201 // The following functions cannot be made efficient on sparse arrays while | 1225 // The following functions cannot be made efficient on sparse arrays while |
1202 // preserving the semantics, since the calls to the receiver function can add | 1226 // preserving the semantics, since the calls to the receiver function can add |
1203 // or delete elements from the array. | 1227 // or delete elements from the array. |
1204 function InnerArrayFilter(f, receiver, array, length) { | 1228 function InnerArrayFilter(f, receiver, array, length, result) { |
1205 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); | 1229 var result_length = 0; |
1206 | |
1207 var accumulator = new InternalArray(); | |
1208 var accumulator_length = 0; | |
1209 var is_array = IS_ARRAY(array); | 1230 var is_array = IS_ARRAY(array); |
1210 for (var i = 0; i < length; i++) { | 1231 for (var i = 0; i < length; i++) { |
1211 if (HAS_INDEX(array, i, is_array)) { | 1232 if (HAS_INDEX(array, i, is_array)) { |
1212 var element = array[i]; | 1233 var element = array[i]; |
1213 if (%_Call(f, receiver, element, i, array)) { | 1234 if (%_Call(f, receiver, element, i, array)) { |
1214 accumulator[accumulator_length++] = element; | 1235 DefineIndexedProperty(result, result_length, element); |
| 1236 result_length++; |
1215 } | 1237 } |
1216 } | 1238 } |
1217 } | 1239 } |
1218 var result = new GlobalArray(); | |
1219 %MoveArrayContents(accumulator, result); | |
1220 return result; | 1240 return result; |
1221 } | 1241 } |
1222 | 1242 |
1223 | 1243 |
| 1244 |
1224 function ArrayFilter(f, receiver) { | 1245 function ArrayFilter(f, receiver) { |
1225 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.filter"); | 1246 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.filter"); |
1226 | 1247 |
1227 // Pull out the length so that modifications to the length in the | 1248 // Pull out the length so that modifications to the length in the |
1228 // loop will not affect the looping and side effects are visible. | 1249 // loop will not affect the looping and side effects are visible. |
1229 var array = TO_OBJECT(this); | 1250 var array = TO_OBJECT(this); |
1230 var length = TO_LENGTH_OR_UINT32(array.length); | 1251 var length = TO_LENGTH_OR_UINT32(array.length); |
1231 return InnerArrayFilter(f, receiver, array, length); | 1252 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); |
| 1253 var result = ArraySpeciesCreate(array, 0); |
| 1254 return InnerArrayFilter(f, receiver, array, length, result); |
1232 } | 1255 } |
1233 | 1256 |
1234 | 1257 |
1235 function InnerArrayForEach(f, receiver, array, length) { | 1258 function InnerArrayForEach(f, receiver, array, length) { |
1236 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); | 1259 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); |
1237 | 1260 |
1238 var is_array = IS_ARRAY(array); | 1261 var is_array = IS_ARRAY(array); |
1239 for (var i = 0; i < length; i++) { | 1262 for (var i = 0; i < length; i++) { |
1240 if (HAS_INDEX(array, i, is_array)) { | 1263 if (HAS_INDEX(array, i, is_array)) { |
1241 var element = array[i]; | 1264 var element = array[i]; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.every"); | 1323 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.every"); |
1301 | 1324 |
1302 // Pull out the length so that modifications to the length in the | 1325 // Pull out the length so that modifications to the length in the |
1303 // loop will not affect the looping and side effects are visible. | 1326 // loop will not affect the looping and side effects are visible. |
1304 var array = TO_OBJECT(this); | 1327 var array = TO_OBJECT(this); |
1305 var length = TO_LENGTH_OR_UINT32(array.length); | 1328 var length = TO_LENGTH_OR_UINT32(array.length); |
1306 return InnerArrayEvery(f, receiver, array, length); | 1329 return InnerArrayEvery(f, receiver, array, length); |
1307 } | 1330 } |
1308 | 1331 |
1309 | 1332 |
1310 function InnerArrayMap(f, receiver, array, length) { | |
1311 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); | |
1312 | |
1313 var accumulator = new InternalArray(length); | |
1314 var is_array = IS_ARRAY(array); | |
1315 for (var i = 0; i < length; i++) { | |
1316 if (HAS_INDEX(array, i, is_array)) { | |
1317 var element = array[i]; | |
1318 accumulator[i] = %_Call(f, receiver, element, i, array); | |
1319 } | |
1320 } | |
1321 var result = new GlobalArray(); | |
1322 %MoveArrayContents(accumulator, result); | |
1323 return result; | |
1324 } | |
1325 | |
1326 | |
1327 function ArrayMap(f, receiver) { | 1333 function ArrayMap(f, receiver) { |
1328 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.map"); | 1334 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.map"); |
1329 | 1335 |
1330 // Pull out the length so that modifications to the length in the | 1336 // Pull out the length so that modifications to the length in the |
1331 // loop will not affect the looping and side effects are visible. | 1337 // loop will not affect the looping and side effects are visible. |
1332 var array = TO_OBJECT(this); | 1338 var array = TO_OBJECT(this); |
1333 var length = TO_LENGTH_OR_UINT32(array.length); | 1339 var length = TO_LENGTH_OR_UINT32(array.length); |
1334 return InnerArrayMap(f, receiver, array, length); | 1340 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); |
| 1341 var result = ArraySpeciesCreate(array, length); |
| 1342 var is_array = IS_ARRAY(array); |
| 1343 for (var i = 0; i < length; i++) { |
| 1344 if (HAS_INDEX(array, i, is_array)) { |
| 1345 var element = array[i]; |
| 1346 DefineIndexedProperty(result, i, %_Call(f, receiver, element, i, array)); |
| 1347 } |
| 1348 } |
| 1349 return result; |
1335 } | 1350 } |
1336 | 1351 |
1337 | 1352 |
1338 // For .indexOf, we don't need to pass in the number of arguments | 1353 // For .indexOf, we don't need to pass in the number of arguments |
1339 // at the callsite since ToInteger(undefined) == 0; however, for | 1354 // at the callsite since ToInteger(undefined) == 0; however, for |
1340 // .lastIndexOf, we need to pass it, since the behavior for passing | 1355 // .lastIndexOf, we need to pass it, since the behavior for passing |
1341 // undefined is 0 but for not including the argument is length-1. | 1356 // undefined is 0 but for not including the argument is length-1. |
1342 function InnerArrayIndexOf(array, element, index, length) { | 1357 function InnerArrayIndexOf(array, element, index, length) { |
1343 if (length == 0) return -1; | 1358 if (length == 0) return -1; |
1344 if (IS_UNDEFINED(index)) { | 1359 if (IS_UNDEFINED(index)) { |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1941 to.InnerArrayEvery = InnerArrayEvery; | 1956 to.InnerArrayEvery = InnerArrayEvery; |
1942 to.InnerArrayFill = InnerArrayFill; | 1957 to.InnerArrayFill = InnerArrayFill; |
1943 to.InnerArrayFilter = InnerArrayFilter; | 1958 to.InnerArrayFilter = InnerArrayFilter; |
1944 to.InnerArrayFind = InnerArrayFind; | 1959 to.InnerArrayFind = InnerArrayFind; |
1945 to.InnerArrayFindIndex = InnerArrayFindIndex; | 1960 to.InnerArrayFindIndex = InnerArrayFindIndex; |
1946 to.InnerArrayForEach = InnerArrayForEach; | 1961 to.InnerArrayForEach = InnerArrayForEach; |
1947 to.InnerArrayIncludes = InnerArrayIncludes; | 1962 to.InnerArrayIncludes = InnerArrayIncludes; |
1948 to.InnerArrayIndexOf = InnerArrayIndexOf; | 1963 to.InnerArrayIndexOf = InnerArrayIndexOf; |
1949 to.InnerArrayJoin = InnerArrayJoin; | 1964 to.InnerArrayJoin = InnerArrayJoin; |
1950 to.InnerArrayLastIndexOf = InnerArrayLastIndexOf; | 1965 to.InnerArrayLastIndexOf = InnerArrayLastIndexOf; |
1951 to.InnerArrayMap = InnerArrayMap; | |
1952 to.InnerArrayReduce = InnerArrayReduce; | 1966 to.InnerArrayReduce = InnerArrayReduce; |
1953 to.InnerArrayReduceRight = InnerArrayReduceRight; | 1967 to.InnerArrayReduceRight = InnerArrayReduceRight; |
1954 to.InnerArraySome = InnerArraySome; | 1968 to.InnerArraySome = InnerArraySome; |
1955 to.InnerArraySort = InnerArraySort; | 1969 to.InnerArraySort = InnerArraySort; |
1956 to.InnerArrayToLocaleString = InnerArrayToLocaleString; | 1970 to.InnerArrayToLocaleString = InnerArrayToLocaleString; |
1957 to.PackedArrayReverse = PackedArrayReverse; | 1971 to.PackedArrayReverse = PackedArrayReverse; |
1958 }); | 1972 }); |
1959 | 1973 |
1960 %InstallToContext([ | 1974 %InstallToContext([ |
1961 "array_pop", ArrayPop, | 1975 "array_pop", ArrayPop, |
1962 "array_push", ArrayPush, | 1976 "array_push", ArrayPush, |
1963 "array_shift", ArrayShift, | 1977 "array_shift", ArrayShift, |
1964 "array_splice", ArraySplice, | 1978 "array_splice", ArraySplice, |
1965 "array_slice", ArraySlice, | 1979 "array_slice", ArraySlice, |
1966 "array_unshift", ArrayUnshift, | 1980 "array_unshift", ArrayUnshift, |
1967 ]); | 1981 ]); |
1968 | 1982 |
1969 }); | 1983 }); |
OLD | NEW |