| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 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 (function(global, utils) { | |
| 6 | |
| 7 'use strict'; | |
| 8 | |
| 9 %CheckIsBootstrapping(); | |
| 10 | |
| 11 // ------------------------------------------------------------------- | |
| 12 // Imports | |
| 13 | |
| 14 var GetIterator; | |
| 15 var GetMethod; | |
| 16 var GlobalArray = global.Array; | |
| 17 var iteratorSymbol = utils.ImportNow("iterator_symbol"); | |
| 18 var MathMax; | |
| 19 var MathMin; | |
| 20 var ObjectIsFrozen; | |
| 21 var ObjectDefineProperty; | |
| 22 | |
| 23 utils.Import(function(from) { | |
| 24 GetIterator = from.GetIterator; | |
| 25 GetMethod = from.GetMethod; | |
| 26 MathMax = from.MathMax; | |
| 27 MathMin = from.MathMin; | |
| 28 ObjectIsFrozen = from.ObjectIsFrozen; | |
| 29 ObjectDefineProperty = from.ObjectDefineProperty; | |
| 30 }); | |
| 31 | |
| 32 // ------------------------------------------------------------------- | |
| 33 | |
| 34 function InnerArrayCopyWithin(target, start, end, array, length) { | |
| 35 target = TO_INTEGER(target); | |
| 36 var to; | |
| 37 if (target < 0) { | |
| 38 to = MathMax(length + target, 0); | |
| 39 } else { | |
| 40 to = MathMin(target, length); | |
| 41 } | |
| 42 | |
| 43 start = TO_INTEGER(start); | |
| 44 var from; | |
| 45 if (start < 0) { | |
| 46 from = MathMax(length + start, 0); | |
| 47 } else { | |
| 48 from = MathMin(start, length); | |
| 49 } | |
| 50 | |
| 51 end = IS_UNDEFINED(end) ? length : TO_INTEGER(end); | |
| 52 var final; | |
| 53 if (end < 0) { | |
| 54 final = MathMax(length + end, 0); | |
| 55 } else { | |
| 56 final = MathMin(end, length); | |
| 57 } | |
| 58 | |
| 59 var count = MathMin(final - from, length - to); | |
| 60 var direction = 1; | |
| 61 if (from < to && to < (from + count)) { | |
| 62 direction = -1; | |
| 63 from = from + count - 1; | |
| 64 to = to + count - 1; | |
| 65 } | |
| 66 | |
| 67 while (count > 0) { | |
| 68 if (from in array) { | |
| 69 array[to] = array[from]; | |
| 70 } else { | |
| 71 delete array[to]; | |
| 72 } | |
| 73 from = from + direction; | |
| 74 to = to + direction; | |
| 75 count--; | |
| 76 } | |
| 77 | |
| 78 return array; | |
| 79 } | |
| 80 | |
| 81 // ES6 draft 03-17-15, section 22.1.3.3 | |
| 82 function ArrayCopyWithin(target, start, end) { | |
| 83 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin"); | |
| 84 | |
| 85 var array = TO_OBJECT(this); | |
| 86 var length = TO_LENGTH(array.length); | |
| 87 | |
| 88 return InnerArrayCopyWithin(target, start, end, array, length); | |
| 89 } | |
| 90 | |
| 91 function InnerArrayFind(predicate, thisArg, array, length) { | |
| 92 if (!IS_CALLABLE(predicate)) { | |
| 93 throw MakeTypeError(kCalledNonCallable, predicate); | |
| 94 } | |
| 95 | |
| 96 for (var i = 0; i < length; i++) { | |
| 97 var element = array[i]; | |
| 98 if (%_Call(predicate, thisArg, element, i, array)) { | |
| 99 return element; | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 return; | |
| 104 } | |
| 105 | |
| 106 // ES6 draft 07-15-13, section 15.4.3.23 | |
| 107 function ArrayFind(predicate, thisArg) { | |
| 108 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find"); | |
| 109 | |
| 110 var array = TO_OBJECT(this); | |
| 111 var length = TO_INTEGER(array.length); | |
| 112 | |
| 113 return InnerArrayFind(predicate, thisArg, array, length); | |
| 114 } | |
| 115 | |
| 116 function InnerArrayFindIndex(predicate, thisArg, array, length) { | |
| 117 if (!IS_CALLABLE(predicate)) { | |
| 118 throw MakeTypeError(kCalledNonCallable, predicate); | |
| 119 } | |
| 120 | |
| 121 for (var i = 0; i < length; i++) { | |
| 122 var element = array[i]; | |
| 123 if (%_Call(predicate, thisArg, element, i, array)) { | |
| 124 return i; | |
| 125 } | |
| 126 } | |
| 127 | |
| 128 return -1; | |
| 129 } | |
| 130 | |
| 131 // ES6 draft 07-15-13, section 15.4.3.24 | |
| 132 function ArrayFindIndex(predicate, thisArg) { | |
| 133 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex"); | |
| 134 | |
| 135 var array = TO_OBJECT(this); | |
| 136 var length = TO_INTEGER(array.length); | |
| 137 | |
| 138 return InnerArrayFindIndex(predicate, thisArg, array, length); | |
| 139 } | |
| 140 | |
| 141 // ES6, draft 04-05-14, section 22.1.3.6 | |
| 142 function InnerArrayFill(value, start, end, array, length) { | |
| 143 var i = IS_UNDEFINED(start) ? 0 : TO_INTEGER(start); | |
| 144 var end = IS_UNDEFINED(end) ? length : TO_INTEGER(end); | |
| 145 | |
| 146 if (i < 0) { | |
| 147 i += length; | |
| 148 if (i < 0) i = 0; | |
| 149 } else { | |
| 150 if (i > length) i = length; | |
| 151 } | |
| 152 | |
| 153 if (end < 0) { | |
| 154 end += length; | |
| 155 if (end < 0) end = 0; | |
| 156 } else { | |
| 157 if (end > length) end = length; | |
| 158 } | |
| 159 | |
| 160 if ((end - i) > 0 && ObjectIsFrozen(array)) { | |
| 161 throw MakeTypeError(kArrayFunctionsOnFrozen); | |
| 162 } | |
| 163 | |
| 164 for (; i < end; i++) | |
| 165 array[i] = value; | |
| 166 return array; | |
| 167 } | |
| 168 | |
| 169 // ES6, draft 04-05-14, section 22.1.3.6 | |
| 170 function ArrayFill(value, start, end) { | |
| 171 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill"); | |
| 172 | |
| 173 var array = TO_OBJECT(this); | |
| 174 var length = TO_LENGTH_OR_UINT32(array.length); | |
| 175 | |
| 176 return InnerArrayFill(value, start, end, array, length); | |
| 177 } | |
| 178 | |
| 179 function AddArrayElement(constructor, array, i, value) { | |
| 180 if (constructor === GlobalArray) { | |
| 181 %AddElement(array, i, value); | |
| 182 } else { | |
| 183 ObjectDefineProperty(array, i, { | |
| 184 value: value, writable: true, configurable: true, enumerable: true | |
| 185 }); | |
| 186 } | |
| 187 } | |
| 188 | |
| 189 // ES6, draft 10-14-14, section 22.1.2.1 | |
| 190 function ArrayFrom(arrayLike, mapfn, receiver) { | |
| 191 var items = TO_OBJECT(arrayLike); | |
| 192 var mapping = !IS_UNDEFINED(mapfn); | |
| 193 | |
| 194 if (mapping) { | |
| 195 if (!IS_CALLABLE(mapfn)) { | |
| 196 throw MakeTypeError(kCalledNonCallable, mapfn); | |
| 197 } | |
| 198 } | |
| 199 | |
| 200 var iterable = GetMethod(items, iteratorSymbol); | |
| 201 var k; | |
| 202 var result; | |
| 203 var mappedValue; | |
| 204 var nextValue; | |
| 205 | |
| 206 if (!IS_UNDEFINED(iterable)) { | |
| 207 result = %IsConstructor(this) ? new this() : []; | |
| 208 | |
| 209 var iterator = GetIterator(items, iterable); | |
| 210 | |
| 211 k = 0; | |
| 212 while (true) { | |
| 213 var next = iterator.next(); | |
| 214 | |
| 215 if (!IS_OBJECT(next)) { | |
| 216 throw MakeTypeError(kIteratorResultNotAnObject, next); | |
| 217 } | |
| 218 | |
| 219 if (next.done) { | |
| 220 result.length = k; | |
| 221 return result; | |
| 222 } | |
| 223 | |
| 224 nextValue = next.value; | |
| 225 if (mapping) { | |
| 226 mappedValue = %_Call(mapfn, receiver, nextValue, k); | |
| 227 } else { | |
| 228 mappedValue = nextValue; | |
| 229 } | |
| 230 AddArrayElement(this, result, k, mappedValue); | |
| 231 k++; | |
| 232 } | |
| 233 } else { | |
| 234 var len = TO_LENGTH(items.length); | |
| 235 result = %IsConstructor(this) ? new this(len) : new GlobalArray(len); | |
| 236 | |
| 237 for (k = 0; k < len; ++k) { | |
| 238 nextValue = items[k]; | |
| 239 if (mapping) { | |
| 240 mappedValue = %_Call(mapfn, receiver, nextValue, k); | |
| 241 } else { | |
| 242 mappedValue = nextValue; | |
| 243 } | |
| 244 AddArrayElement(this, result, k, mappedValue); | |
| 245 } | |
| 246 | |
| 247 result.length = k; | |
| 248 return result; | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 // ES6, draft 05-22-14, section 22.1.2.3 | |
| 253 function ArrayOf() { | |
| 254 var length = %_ArgumentsLength(); | |
| 255 var constructor = this; | |
| 256 // TODO: Implement IsConstructor (ES6 section 7.2.5) | |
| 257 var array = %IsConstructor(constructor) ? new constructor(length) : []; | |
| 258 for (var i = 0; i < length; i++) { | |
| 259 AddArrayElement(constructor, array, i, %_Arguments(i)); | |
| 260 } | |
| 261 array.length = length; | |
| 262 return array; | |
| 263 } | |
| 264 | |
| 265 // ------------------------------------------------------------------- | |
| 266 | |
| 267 %FunctionSetLength(ArrayCopyWithin, 2); | |
| 268 %FunctionSetLength(ArrayFrom, 1); | |
| 269 %FunctionSetLength(ArrayFill, 1); | |
| 270 %FunctionSetLength(ArrayFind, 1); | |
| 271 %FunctionSetLength(ArrayFindIndex, 1); | |
| 272 | |
| 273 // Set up non-enumerable functions on the Array object. | |
| 274 utils.InstallFunctions(GlobalArray, DONT_ENUM, [ | |
| 275 "from", ArrayFrom, | |
| 276 "of", ArrayOf | |
| 277 ]); | |
| 278 | |
| 279 // Set up the non-enumerable functions on the Array prototype object. | |
| 280 utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [ | |
| 281 "copyWithin", ArrayCopyWithin, | |
| 282 "find", ArrayFind, | |
| 283 "findIndex", ArrayFindIndex, | |
| 284 "fill", ArrayFill | |
| 285 ]); | |
| 286 | |
| 287 // ------------------------------------------------------------------- | |
| 288 // Exports | |
| 289 | |
| 290 utils.Export(function(to) { | |
| 291 to.ArrayFrom = ArrayFrom; | |
| 292 to.InnerArrayCopyWithin = InnerArrayCopyWithin; | |
| 293 to.InnerArrayFill = InnerArrayFill; | |
| 294 to.InnerArrayFind = InnerArrayFind; | |
| 295 to.InnerArrayFindIndex = InnerArrayFindIndex; | |
| 296 }); | |
| 297 | |
| 298 }) | |
| OLD | NEW |