| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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 |  | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 14 | var AddIndexedProperty; | 
|  | 15 | // array.js has to come before typedarray.js for this to work | 
|  | 16 | var ArrayToString = utils.ImportNow("ArrayToString"); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 17 | var ArrayValues; | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 18 | var GetIterator; | 
|  | 19 | var GetMethod; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 20 | var GlobalArray = global.Array; | 
|  | 21 | var GlobalArrayBuffer = global.ArrayBuffer; | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 22 | var GlobalArrayBufferPrototype = GlobalArrayBuffer.prototype; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 23 | var GlobalDataView = global.DataView; | 
|  | 24 | var GlobalObject = global.Object; | 
|  | 25 | var InternalArray = utils.InternalArray; | 
|  | 26 | var InnerArrayCopyWithin; | 
|  | 27 | var InnerArrayEvery; | 
|  | 28 | var InnerArrayFill; | 
|  | 29 | var InnerArrayFilter; | 
|  | 30 | var InnerArrayFind; | 
|  | 31 | var InnerArrayFindIndex; | 
|  | 32 | var InnerArrayForEach; | 
|  | 33 | var InnerArrayIncludes; | 
|  | 34 | var InnerArrayIndexOf; | 
|  | 35 | var InnerArrayJoin; | 
|  | 36 | var InnerArrayLastIndexOf; | 
|  | 37 | var InnerArrayReduce; | 
|  | 38 | var InnerArrayReduceRight; | 
|  | 39 | var InnerArraySome; | 
|  | 40 | var InnerArraySort; | 
|  | 41 | var InnerArrayToLocaleString; | 
|  | 42 | var InternalArray = utils.InternalArray; | 
|  | 43 | var IsNaN; | 
|  | 44 | var MakeRangeError; | 
|  | 45 | var MakeTypeError; | 
|  | 46 | var MaxSimple; | 
|  | 47 | var MinSimple; | 
|  | 48 | var PackedArrayReverse; | 
|  | 49 | var SpeciesConstructor; | 
|  | 50 | var ToPositiveInteger; | 
|  | 51 | var iteratorSymbol = utils.ImportNow("iterator_symbol"); | 
|  | 52 | var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); | 
|  | 53 |  | 
|  | 54 | macro TYPED_ARRAYS(FUNCTION) | 
|  | 55 | // arrayIds below should be synchronized with Runtime_TypedArrayInitialize. | 
|  | 56 | FUNCTION(1, Uint8Array, 1) | 
|  | 57 | FUNCTION(2, Int8Array, 1) | 
|  | 58 | FUNCTION(3, Uint16Array, 2) | 
|  | 59 | FUNCTION(4, Int16Array, 2) | 
|  | 60 | FUNCTION(5, Uint32Array, 4) | 
|  | 61 | FUNCTION(6, Int32Array, 4) | 
|  | 62 | FUNCTION(7, Float32Array, 4) | 
|  | 63 | FUNCTION(8, Float64Array, 8) | 
|  | 64 | FUNCTION(9, Uint8ClampedArray, 1) | 
|  | 65 | endmacro | 
|  | 66 |  | 
|  | 67 | macro DECLARE_GLOBALS(INDEX, NAME, SIZE) | 
|  | 68 | var GlobalNAME = global.NAME; | 
|  | 69 | endmacro | 
|  | 70 |  | 
|  | 71 | TYPED_ARRAYS(DECLARE_GLOBALS) | 
|  | 72 |  | 
|  | 73 | utils.Import(function(from) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 74 | AddIndexedProperty = from.AddIndexedProperty; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 75 | ArrayValues = from.ArrayValues; | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 76 | GetIterator = from.GetIterator; | 
|  | 77 | GetMethod = from.GetMethod; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 78 | InnerArrayCopyWithin = from.InnerArrayCopyWithin; | 
|  | 79 | InnerArrayEvery = from.InnerArrayEvery; | 
|  | 80 | InnerArrayFill = from.InnerArrayFill; | 
|  | 81 | InnerArrayFilter = from.InnerArrayFilter; | 
|  | 82 | InnerArrayFind = from.InnerArrayFind; | 
|  | 83 | InnerArrayFindIndex = from.InnerArrayFindIndex; | 
|  | 84 | InnerArrayForEach = from.InnerArrayForEach; | 
|  | 85 | InnerArrayIncludes = from.InnerArrayIncludes; | 
|  | 86 | InnerArrayIndexOf = from.InnerArrayIndexOf; | 
|  | 87 | InnerArrayJoin = from.InnerArrayJoin; | 
|  | 88 | InnerArrayLastIndexOf = from.InnerArrayLastIndexOf; | 
|  | 89 | InnerArrayReduce = from.InnerArrayReduce; | 
|  | 90 | InnerArrayReduceRight = from.InnerArrayReduceRight; | 
|  | 91 | InnerArraySome = from.InnerArraySome; | 
|  | 92 | InnerArraySort = from.InnerArraySort; | 
|  | 93 | InnerArrayToLocaleString = from.InnerArrayToLocaleString; | 
|  | 94 | IsNaN = from.IsNaN; | 
|  | 95 | MakeRangeError = from.MakeRangeError; | 
|  | 96 | MakeTypeError = from.MakeTypeError; | 
|  | 97 | MaxSimple = from.MaxSimple; | 
|  | 98 | MinSimple = from.MinSimple; | 
|  | 99 | PackedArrayReverse = from.PackedArrayReverse; | 
|  | 100 | SpeciesConstructor = from.SpeciesConstructor; | 
|  | 101 | ToPositiveInteger = from.ToPositiveInteger; | 
|  | 102 | }); | 
|  | 103 |  | 
|  | 104 | // --------------- Typed Arrays --------------------- | 
|  | 105 |  | 
|  | 106 | function TypedArrayDefaultConstructor(typedArray) { | 
|  | 107 | switch (%_ClassOf(typedArray)) { | 
|  | 108 | macro TYPED_ARRAY_CONSTRUCTOR_CASE(ARRAY_ID, NAME, ELEMENT_SIZE) | 
|  | 109 | case "NAME": | 
|  | 110 | return GlobalNAME; | 
|  | 111 | endmacro | 
|  | 112 | TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR_CASE) | 
|  | 113 | } | 
|  | 114 | // The TypeError should not be generated since all callers should | 
|  | 115 | // have already called ValidateTypedArray. | 
|  | 116 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 117 | "TypedArrayDefaultConstructor", this); | 
|  | 118 | } | 
|  | 119 |  | 
|  | 120 | function TypedArrayCreate(constructor, arg0, arg1, arg2) { | 
|  | 121 | if (IS_UNDEFINED(arg1)) { | 
|  | 122 | var newTypedArray = new constructor(arg0); | 
|  | 123 | } else { | 
|  | 124 | var newTypedArray = new constructor(arg0, arg1, arg2); | 
|  | 125 | } | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 126 | if (!IS_TYPEDARRAY(newTypedArray)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 127 | // TODO(littledan): Check for being detached, here and elsewhere | 
|  | 128 | // All callers where the first argument is a Number have no additional | 
|  | 129 | // arguments. | 
|  | 130 | if (IS_NUMBER(arg0) && %_TypedArrayGetLength(newTypedArray) < arg0) { | 
|  | 131 | throw MakeTypeError(kTypedArrayTooShort); | 
|  | 132 | } | 
|  | 133 | return newTypedArray; | 
|  | 134 | } | 
|  | 135 |  | 
|  | 136 | function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2, conservative) { | 
|  | 137 | var defaultConstructor = TypedArrayDefaultConstructor(exemplar); | 
|  | 138 | var constructor = SpeciesConstructor(exemplar, defaultConstructor, | 
|  | 139 | conservative); | 
|  | 140 | return TypedArrayCreate(constructor, arg0, arg1, arg2); | 
|  | 141 | } | 
|  | 142 |  | 
|  | 143 | macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) | 
|  | 144 | function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) { | 
|  | 145 | if (!IS_UNDEFINED(byteOffset)) { | 
|  | 146 | byteOffset = ToPositiveInteger(byteOffset, kInvalidTypedArrayLength); | 
|  | 147 | } | 
|  | 148 | if (!IS_UNDEFINED(length)) { | 
|  | 149 | length = ToPositiveInteger(length, kInvalidTypedArrayLength); | 
|  | 150 | } | 
|  | 151 |  | 
|  | 152 | var bufferByteLength = %_ArrayBufferGetByteLength(buffer); | 
|  | 153 | var offset; | 
|  | 154 | if (IS_UNDEFINED(byteOffset)) { | 
|  | 155 | offset = 0; | 
|  | 156 | } else { | 
|  | 157 | offset = byteOffset; | 
|  | 158 |  | 
|  | 159 | if (offset % ELEMENT_SIZE !== 0) { | 
|  | 160 | throw MakeRangeError(kInvalidTypedArrayAlignment, | 
|  | 161 | "start offset", "NAME", ELEMENT_SIZE); | 
|  | 162 | } | 
|  | 163 | if (offset > bufferByteLength) { | 
|  | 164 | throw MakeRangeError(kInvalidTypedArrayOffset); | 
|  | 165 | } | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | var newByteLength; | 
|  | 169 | var newLength; | 
|  | 170 | if (IS_UNDEFINED(length)) { | 
|  | 171 | if (bufferByteLength % ELEMENT_SIZE !== 0) { | 
|  | 172 | throw MakeRangeError(kInvalidTypedArrayAlignment, | 
|  | 173 | "byte length", "NAME", ELEMENT_SIZE); | 
|  | 174 | } | 
|  | 175 | newByteLength = bufferByteLength - offset; | 
|  | 176 | newLength = newByteLength / ELEMENT_SIZE; | 
|  | 177 | } else { | 
|  | 178 | var newLength = length; | 
|  | 179 | newByteLength = newLength * ELEMENT_SIZE; | 
|  | 180 | } | 
|  | 181 | if ((offset + newByteLength > bufferByteLength) | 
|  | 182 | || (newLength > %_MaxSmi())) { | 
|  | 183 | throw MakeRangeError(kInvalidTypedArrayLength); | 
|  | 184 | } | 
|  | 185 | %_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength, true); | 
|  | 186 | } | 
|  | 187 |  | 
|  | 188 | function NAMEConstructByLength(obj, length) { | 
|  | 189 | var l = IS_UNDEFINED(length) ? | 
|  | 190 | 0 : ToPositiveInteger(length, kInvalidTypedArrayLength); | 
|  | 191 | if (l > %_MaxSmi()) { | 
|  | 192 | throw MakeRangeError(kInvalidTypedArrayLength); | 
|  | 193 | } | 
|  | 194 | var byteLength = l * ELEMENT_SIZE; | 
|  | 195 | if (byteLength > %_TypedArrayMaxSizeInHeap()) { | 
|  | 196 | var buffer = new GlobalArrayBuffer(byteLength); | 
|  | 197 | %_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength, true); | 
|  | 198 | } else { | 
|  | 199 | %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, true); | 
|  | 200 | } | 
|  | 201 | } | 
|  | 202 |  | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 203 | function NAMEConstructByArrayLike(obj, arrayLike, length) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 204 | var l = ToPositiveInteger(length, kInvalidTypedArrayLength); | 
|  | 205 |  | 
|  | 206 | if (l > %_MaxSmi()) { | 
|  | 207 | throw MakeRangeError(kInvalidTypedArrayLength); | 
|  | 208 | } | 
|  | 209 | var initialized = false; | 
|  | 210 | var byteLength = l * ELEMENT_SIZE; | 
|  | 211 | if (byteLength <= %_TypedArrayMaxSizeInHeap()) { | 
|  | 212 | %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, false); | 
|  | 213 | } else { | 
|  | 214 | initialized = | 
|  | 215 | %TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l); | 
|  | 216 | } | 
|  | 217 | if (!initialized) { | 
|  | 218 | for (var i = 0; i < l; i++) { | 
|  | 219 | // It is crucial that we let any execptions from arrayLike[i] | 
|  | 220 | // propagate outside the function. | 
|  | 221 | obj[i] = arrayLike[i]; | 
|  | 222 | } | 
|  | 223 | } | 
|  | 224 | } | 
|  | 225 |  | 
|  | 226 | function NAMEConstructByIterable(obj, iterable, iteratorFn) { | 
|  | 227 | var list = new InternalArray(); | 
|  | 228 | // Reading the Symbol.iterator property of iterable twice would be | 
|  | 229 | // observable with getters, so instead, we call the function which | 
|  | 230 | // was already looked up, and wrap it in another iterable. The | 
|  | 231 | // __proto__ of the new iterable is set to null to avoid any chance | 
|  | 232 | // of modifications to Object.prototype being observable here. | 
|  | 233 | var iterator = %_Call(iteratorFn, iterable); | 
|  | 234 | var newIterable = { | 
|  | 235 | __proto__: null | 
|  | 236 | }; | 
|  | 237 | // TODO(littledan): Computed properties don't work yet in nosnap. | 
|  | 238 | // Rephrase when they do. | 
|  | 239 | newIterable[iteratorSymbol] = function() { return iterator; } | 
|  | 240 | for (var value of newIterable) { | 
|  | 241 | list.push(value); | 
|  | 242 | } | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 243 | NAMEConstructByArrayLike(obj, list, list.length); | 
|  | 244 | } | 
|  | 245 |  | 
|  | 246 | // ES#sec-typedarray-typedarray TypedArray ( typedArray ) | 
|  | 247 | function NAMEConstructByTypedArray(obj, typedArray) { | 
|  | 248 | // TODO(littledan): Throw on detached typedArray | 
|  | 249 | var srcData = %TypedArrayGetBuffer(typedArray); | 
|  | 250 | var length = %_TypedArrayGetLength(typedArray); | 
|  | 251 | var byteLength = %_ArrayBufferViewGetByteLength(typedArray); | 
|  | 252 | var newByteLength = length * ELEMENT_SIZE; | 
|  | 253 | NAMEConstructByArrayLike(obj, typedArray, length); | 
|  | 254 | var bufferConstructor = SpeciesConstructor(srcData, GlobalArrayBuffer); | 
|  | 255 | var prototype = bufferConstructor.prototype; | 
|  | 256 | // TODO(littledan): Use the right prototype based on bufferConstructor's realm | 
|  | 257 | if (IS_RECEIVER(prototype) && prototype !== GlobalArrayBufferPrototype) { | 
|  | 258 | %InternalSetPrototype(%TypedArrayGetBuffer(obj), prototype); | 
|  | 259 | } | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 260 | } | 
|  | 261 |  | 
|  | 262 | function NAMEConstructor(arg1, arg2, arg3) { | 
|  | 263 | if (!IS_UNDEFINED(new.target)) { | 
|  | 264 | if (IS_ARRAYBUFFER(arg1) || IS_SHAREDARRAYBUFFER(arg1)) { | 
|  | 265 | NAMEConstructByArrayBuffer(this, arg1, arg2, arg3); | 
|  | 266 | } else if (IS_NUMBER(arg1) || IS_STRING(arg1) || | 
|  | 267 | IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) { | 
|  | 268 | NAMEConstructByLength(this, arg1); | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 269 | } else if (IS_TYPEDARRAY(arg1)) { | 
|  | 270 | NAMEConstructByTypedArray(this, arg1); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 271 | } else { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 272 | var iteratorFn = arg1[iteratorSymbol]; | 
|  | 273 | if (IS_UNDEFINED(iteratorFn) || iteratorFn === ArrayValues) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 274 | NAMEConstructByArrayLike(this, arg1, arg1.length); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 275 | } else { | 
|  | 276 | NAMEConstructByIterable(this, arg1, iteratorFn); | 
|  | 277 | } | 
|  | 278 | } | 
|  | 279 | } else { | 
|  | 280 | throw MakeTypeError(kConstructorNotFunction, "NAME") | 
|  | 281 | } | 
|  | 282 | } | 
|  | 283 |  | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 284 | function NAMESubArray(begin, end) { | 
|  | 285 | var beginInt = TO_INTEGER(begin); | 
|  | 286 | if (!IS_UNDEFINED(end)) { | 
|  | 287 | var endInt = TO_INTEGER(end); | 
|  | 288 | var srcLength = %_TypedArrayGetLength(this); | 
|  | 289 | } else { | 
|  | 290 | var srcLength = %_TypedArrayGetLength(this); | 
|  | 291 | var endInt = srcLength; | 
|  | 292 | } | 
|  | 293 |  | 
|  | 294 | if (beginInt < 0) { | 
|  | 295 | beginInt = MaxSimple(0, srcLength + beginInt); | 
|  | 296 | } else { | 
|  | 297 | beginInt = MinSimple(beginInt, srcLength); | 
|  | 298 | } | 
|  | 299 |  | 
|  | 300 | if (endInt < 0) { | 
|  | 301 | endInt = MaxSimple(0, srcLength + endInt); | 
|  | 302 | } else { | 
|  | 303 | endInt = MinSimple(endInt, srcLength); | 
|  | 304 | } | 
|  | 305 |  | 
|  | 306 | if (endInt < beginInt) { | 
|  | 307 | endInt = beginInt; | 
|  | 308 | } | 
|  | 309 |  | 
|  | 310 | var newLength = endInt - beginInt; | 
|  | 311 | var beginByteOffset = | 
|  | 312 | %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE; | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 313 | // BUG(v8:4665): For web compatibility, subarray needs to always build an | 
|  | 314 | // instance of the default constructor. | 
|  | 315 | // TODO(littledan): Switch to the standard or standardize the fix | 
|  | 316 | return new GlobalNAME(%TypedArrayGetBuffer(this), beginByteOffset, newLength); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 317 | } | 
|  | 318 | endmacro | 
|  | 319 |  | 
|  | 320 | TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR) | 
|  | 321 |  | 
|  | 322 | function TypedArraySubArray(begin, end) { | 
|  | 323 | switch (%_ClassOf(this)) { | 
|  | 324 | macro TYPED_ARRAY_SUBARRAY_CASE(ARRAY_ID, NAME, ELEMENT_SIZE) | 
|  | 325 | case "NAME": | 
|  | 326 | return %_Call(NAMESubArray, this, begin, end); | 
|  | 327 | endmacro | 
|  | 328 | TYPED_ARRAYS(TYPED_ARRAY_SUBARRAY_CASE) | 
|  | 329 | } | 
|  | 330 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 331 | "get TypedArray.prototype.subarray", this); | 
|  | 332 | } | 
|  | 333 | %SetForceInlineFlag(TypedArraySubArray); | 
|  | 334 |  | 
|  | 335 | function TypedArrayGetBuffer() { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 336 | if (!IS_TYPEDARRAY(this)) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 337 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 338 | "get TypedArray.prototype.buffer", this); | 
|  | 339 | } | 
|  | 340 | return %TypedArrayGetBuffer(this); | 
|  | 341 | } | 
|  | 342 | %SetForceInlineFlag(TypedArrayGetBuffer); | 
|  | 343 |  | 
|  | 344 | function TypedArrayGetByteLength() { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 345 | if (!IS_TYPEDARRAY(this)) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 346 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 347 | "get TypedArray.prototype.byteLength", this); | 
|  | 348 | } | 
|  | 349 | return %_ArrayBufferViewGetByteLength(this); | 
|  | 350 | } | 
|  | 351 | %SetForceInlineFlag(TypedArrayGetByteLength); | 
|  | 352 |  | 
|  | 353 | function TypedArrayGetByteOffset() { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 354 | if (!IS_TYPEDARRAY(this)) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 355 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 356 | "get TypedArray.prototype.byteOffset", this); | 
|  | 357 | } | 
|  | 358 | return %_ArrayBufferViewGetByteOffset(this); | 
|  | 359 | } | 
|  | 360 | %SetForceInlineFlag(TypedArrayGetByteOffset); | 
|  | 361 |  | 
|  | 362 | function TypedArrayGetLength() { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 363 | if (!IS_TYPEDARRAY(this)) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 364 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 365 | "get TypedArray.prototype.length", this); | 
|  | 366 | } | 
|  | 367 | return %_TypedArrayGetLength(this); | 
|  | 368 | } | 
|  | 369 | %SetForceInlineFlag(TypedArrayGetLength); | 
|  | 370 |  | 
|  | 371 |  | 
|  | 372 |  | 
|  | 373 | function TypedArraySetFromArrayLike(target, source, sourceLength, offset) { | 
|  | 374 | if (offset > 0) { | 
|  | 375 | for (var i = 0; i < sourceLength; i++) { | 
|  | 376 | target[offset + i] = source[i]; | 
|  | 377 | } | 
|  | 378 | } | 
|  | 379 | else { | 
|  | 380 | for (var i = 0; i < sourceLength; i++) { | 
|  | 381 | target[i] = source[i]; | 
|  | 382 | } | 
|  | 383 | } | 
|  | 384 | } | 
|  | 385 |  | 
|  | 386 | function TypedArraySetFromOverlappingTypedArray(target, source, offset) { | 
|  | 387 | var sourceElementSize = source.BYTES_PER_ELEMENT; | 
|  | 388 | var targetElementSize = target.BYTES_PER_ELEMENT; | 
|  | 389 | var sourceLength = source.length; | 
|  | 390 |  | 
|  | 391 | // Copy left part. | 
|  | 392 | function CopyLeftPart() { | 
|  | 393 | // First un-mutated byte after the next write | 
|  | 394 | var targetPtr = target.byteOffset + (offset + 1) * targetElementSize; | 
|  | 395 | // Next read at sourcePtr. We do not care for memory changing before | 
|  | 396 | // sourcePtr - we have already copied it. | 
|  | 397 | var sourcePtr = source.byteOffset; | 
|  | 398 | for (var leftIndex = 0; | 
|  | 399 | leftIndex < sourceLength && targetPtr <= sourcePtr; | 
|  | 400 | leftIndex++) { | 
|  | 401 | target[offset + leftIndex] = source[leftIndex]; | 
|  | 402 | targetPtr += targetElementSize; | 
|  | 403 | sourcePtr += sourceElementSize; | 
|  | 404 | } | 
|  | 405 | return leftIndex; | 
|  | 406 | } | 
|  | 407 | var leftIndex = CopyLeftPart(); | 
|  | 408 |  | 
|  | 409 | // Copy rigth part; | 
|  | 410 | function CopyRightPart() { | 
|  | 411 | // First unmutated byte before the next write | 
|  | 412 | var targetPtr = | 
|  | 413 | target.byteOffset + (offset + sourceLength - 1) * targetElementSize; | 
|  | 414 | // Next read before sourcePtr. We do not care for memory changing after | 
|  | 415 | // sourcePtr - we have already copied it. | 
|  | 416 | var sourcePtr = | 
|  | 417 | source.byteOffset + sourceLength * sourceElementSize; | 
|  | 418 | for(var rightIndex = sourceLength - 1; | 
|  | 419 | rightIndex >= leftIndex && targetPtr >= sourcePtr; | 
|  | 420 | rightIndex--) { | 
|  | 421 | target[offset + rightIndex] = source[rightIndex]; | 
|  | 422 | targetPtr -= targetElementSize; | 
|  | 423 | sourcePtr -= sourceElementSize; | 
|  | 424 | } | 
|  | 425 | return rightIndex; | 
|  | 426 | } | 
|  | 427 | var rightIndex = CopyRightPart(); | 
|  | 428 |  | 
|  | 429 | var temp = new GlobalArray(rightIndex + 1 - leftIndex); | 
|  | 430 | for (var i = leftIndex; i <= rightIndex; i++) { | 
|  | 431 | temp[i - leftIndex] = source[i]; | 
|  | 432 | } | 
|  | 433 | for (i = leftIndex; i <= rightIndex; i++) { | 
|  | 434 | target[offset + i] = temp[i - leftIndex]; | 
|  | 435 | } | 
|  | 436 | } | 
|  | 437 |  | 
|  | 438 | function TypedArraySet(obj, offset) { | 
|  | 439 | var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset); | 
|  | 440 | if (intOffset < 0) throw MakeTypeError(kTypedArraySetNegativeOffset); | 
|  | 441 |  | 
|  | 442 | if (intOffset > %_MaxSmi()) { | 
|  | 443 | throw MakeRangeError(kTypedArraySetSourceTooLarge); | 
|  | 444 | } | 
|  | 445 | switch (%TypedArraySetFastCases(this, obj, intOffset)) { | 
|  | 446 | // These numbers should be synchronized with runtime.cc. | 
|  | 447 | case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE | 
|  | 448 | return; | 
|  | 449 | case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING | 
|  | 450 | TypedArraySetFromOverlappingTypedArray(this, obj, intOffset); | 
|  | 451 | return; | 
|  | 452 | case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING | 
|  | 453 | TypedArraySetFromArrayLike(this, obj, obj.length, intOffset); | 
|  | 454 | return; | 
|  | 455 | case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY | 
|  | 456 | var l = obj.length; | 
|  | 457 | if (IS_UNDEFINED(l)) { | 
|  | 458 | if (IS_NUMBER(obj)) { | 
|  | 459 | // For number as a first argument, throw TypeError | 
|  | 460 | // instead of silently ignoring the call, so that | 
|  | 461 | // the user knows (s)he did something wrong. | 
|  | 462 | // (Consistent with Firefox and Blink/WebKit) | 
|  | 463 | throw MakeTypeError(kInvalidArgument); | 
|  | 464 | } | 
|  | 465 | return; | 
|  | 466 | } | 
|  | 467 | l = TO_LENGTH(l); | 
|  | 468 | if (intOffset + l > this.length) { | 
|  | 469 | throw MakeRangeError(kTypedArraySetSourceTooLarge); | 
|  | 470 | } | 
|  | 471 | TypedArraySetFromArrayLike(this, obj, l, intOffset); | 
|  | 472 | return; | 
|  | 473 | } | 
|  | 474 | } | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 475 | %FunctionSetLength(TypedArraySet, 1); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 476 |  | 
|  | 477 | function TypedArrayGetToStringTag() { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 478 | if (!IS_TYPEDARRAY(this)) return; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 479 | var name = %_ClassOf(this); | 
|  | 480 | if (IS_UNDEFINED(name)) return; | 
|  | 481 | return name; | 
|  | 482 | } | 
|  | 483 |  | 
|  | 484 |  | 
|  | 485 | function TypedArrayCopyWithin(target, start, end) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 486 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 487 |  | 
|  | 488 | var length = %_TypedArrayGetLength(this); | 
|  | 489 |  | 
|  | 490 | // TODO(littledan): Replace with a memcpy for better performance | 
|  | 491 | return InnerArrayCopyWithin(target, start, end, this, length); | 
|  | 492 | } | 
|  | 493 | %FunctionSetLength(TypedArrayCopyWithin, 2); | 
|  | 494 |  | 
|  | 495 |  | 
|  | 496 | // ES6 draft 05-05-15, section 22.2.3.7 | 
|  | 497 | function TypedArrayEvery(f, receiver) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 498 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 499 |  | 
|  | 500 | var length = %_TypedArrayGetLength(this); | 
|  | 501 |  | 
|  | 502 | return InnerArrayEvery(f, receiver, this, length); | 
|  | 503 | } | 
|  | 504 | %FunctionSetLength(TypedArrayEvery, 1); | 
|  | 505 |  | 
|  | 506 |  | 
|  | 507 | // ES6 draft 08-24-14, section 22.2.3.12 | 
|  | 508 | function TypedArrayForEach(f, receiver) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 509 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 510 |  | 
|  | 511 | var length = %_TypedArrayGetLength(this); | 
|  | 512 |  | 
|  | 513 | InnerArrayForEach(f, receiver, this, length); | 
|  | 514 | } | 
|  | 515 | %FunctionSetLength(TypedArrayForEach, 1); | 
|  | 516 |  | 
|  | 517 |  | 
|  | 518 | // ES6 draft 04-05-14 section 22.2.3.8 | 
|  | 519 | function TypedArrayFill(value, start, end) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 520 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 521 |  | 
|  | 522 | var length = %_TypedArrayGetLength(this); | 
|  | 523 |  | 
|  | 524 | return InnerArrayFill(value, start, end, this, length); | 
|  | 525 | } | 
|  | 526 | %FunctionSetLength(TypedArrayFill, 1); | 
|  | 527 |  | 
|  | 528 |  | 
|  | 529 | // ES6 draft 07-15-13, section 22.2.3.9 | 
|  | 530 | function TypedArrayFilter(f, thisArg) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 531 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 532 |  | 
|  | 533 | var length = %_TypedArrayGetLength(this); | 
|  | 534 | if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); | 
|  | 535 | var result = new InternalArray(); | 
|  | 536 | InnerArrayFilter(f, thisArg, this, length, result); | 
|  | 537 | var captured = result.length; | 
|  | 538 | var output = TypedArraySpeciesCreate(this, captured); | 
|  | 539 | for (var i = 0; i < captured; i++) { | 
|  | 540 | output[i] = result[i]; | 
|  | 541 | } | 
|  | 542 | return output; | 
|  | 543 | } | 
|  | 544 | %FunctionSetLength(TypedArrayFilter, 1); | 
|  | 545 |  | 
|  | 546 |  | 
|  | 547 | // ES6 draft 07-15-13, section 22.2.3.10 | 
|  | 548 | function TypedArrayFind(predicate, thisArg) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 549 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 550 |  | 
|  | 551 | var length = %_TypedArrayGetLength(this); | 
|  | 552 |  | 
|  | 553 | return InnerArrayFind(predicate, thisArg, this, length); | 
|  | 554 | } | 
|  | 555 | %FunctionSetLength(TypedArrayFind, 1); | 
|  | 556 |  | 
|  | 557 |  | 
|  | 558 | // ES6 draft 07-15-13, section 22.2.3.11 | 
|  | 559 | function TypedArrayFindIndex(predicate, thisArg) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 560 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 561 |  | 
|  | 562 | var length = %_TypedArrayGetLength(this); | 
|  | 563 |  | 
|  | 564 | return InnerArrayFindIndex(predicate, thisArg, this, length); | 
|  | 565 | } | 
|  | 566 | %FunctionSetLength(TypedArrayFindIndex, 1); | 
|  | 567 |  | 
|  | 568 |  | 
|  | 569 | // ES6 draft 05-18-15, section 22.2.3.21 | 
|  | 570 | function TypedArrayReverse() { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 571 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 572 |  | 
|  | 573 | var length = %_TypedArrayGetLength(this); | 
|  | 574 |  | 
|  | 575 | return PackedArrayReverse(this, length); | 
|  | 576 | } | 
|  | 577 |  | 
|  | 578 |  | 
|  | 579 | function TypedArrayComparefn(x, y) { | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 580 | if (x === 0 && x === y) { | 
|  | 581 | x = 1 / x; | 
|  | 582 | y = 1 / y; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 583 | } | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 584 | if (x < y) { | 
|  | 585 | return -1; | 
|  | 586 | } else if (x > y) { | 
|  | 587 | return 1; | 
|  | 588 | } else if (IsNaN(x) && IsNaN(y)) { | 
|  | 589 | return IsNaN(y) ? 0 : 1; | 
|  | 590 | } else if (IsNaN(x)) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 591 | return 1; | 
|  | 592 | } | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 593 | return 0; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 594 | } | 
|  | 595 |  | 
|  | 596 |  | 
|  | 597 | // ES6 draft 05-18-15, section 22.2.3.25 | 
|  | 598 | function TypedArraySort(comparefn) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 599 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 600 |  | 
|  | 601 | var length = %_TypedArrayGetLength(this); | 
|  | 602 |  | 
|  | 603 | if (IS_UNDEFINED(comparefn)) { | 
|  | 604 | comparefn = TypedArrayComparefn; | 
|  | 605 | } | 
|  | 606 |  | 
|  | 607 | return InnerArraySort(this, length, comparefn); | 
|  | 608 | } | 
|  | 609 |  | 
|  | 610 |  | 
|  | 611 | // ES6 section 22.2.3.13 | 
|  | 612 | function TypedArrayIndexOf(element, index) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 613 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 614 |  | 
|  | 615 | var length = %_TypedArrayGetLength(this); | 
|  | 616 | return InnerArrayIndexOf(this, element, index, length); | 
|  | 617 | } | 
|  | 618 | %FunctionSetLength(TypedArrayIndexOf, 1); | 
|  | 619 |  | 
|  | 620 |  | 
|  | 621 | // ES6 section 22.2.3.16 | 
|  | 622 | function TypedArrayLastIndexOf(element, index) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 623 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 624 |  | 
|  | 625 | var length = %_TypedArrayGetLength(this); | 
|  | 626 |  | 
|  | 627 | return InnerArrayLastIndexOf(this, element, index, length, | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 628 | arguments.length); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 629 | } | 
|  | 630 | %FunctionSetLength(TypedArrayLastIndexOf, 1); | 
|  | 631 |  | 
|  | 632 |  | 
|  | 633 | // ES6 draft 07-15-13, section 22.2.3.18 | 
|  | 634 | function TypedArrayMap(f, thisArg) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 635 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 636 |  | 
|  | 637 | var length = %_TypedArrayGetLength(this); | 
|  | 638 | var result = TypedArraySpeciesCreate(this, length); | 
|  | 639 | if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); | 
|  | 640 | for (var i = 0; i < length; i++) { | 
|  | 641 | var element = this[i]; | 
|  | 642 | result[i] = %_Call(f, thisArg, element, i, this); | 
|  | 643 | } | 
|  | 644 | return result; | 
|  | 645 | } | 
|  | 646 | %FunctionSetLength(TypedArrayMap, 1); | 
|  | 647 |  | 
|  | 648 |  | 
|  | 649 | // ES6 draft 05-05-15, section 22.2.3.24 | 
|  | 650 | function TypedArraySome(f, receiver) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 651 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 652 |  | 
|  | 653 | var length = %_TypedArrayGetLength(this); | 
|  | 654 |  | 
|  | 655 | return InnerArraySome(f, receiver, this, length); | 
|  | 656 | } | 
|  | 657 | %FunctionSetLength(TypedArraySome, 1); | 
|  | 658 |  | 
|  | 659 |  | 
|  | 660 | // ES6 section 22.2.3.27 | 
|  | 661 | function TypedArrayToLocaleString() { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 662 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 663 |  | 
|  | 664 | var length = %_TypedArrayGetLength(this); | 
|  | 665 |  | 
|  | 666 | return InnerArrayToLocaleString(this, length); | 
|  | 667 | } | 
|  | 668 |  | 
|  | 669 |  | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 670 | // ES6 section 22.2.3.14 | 
|  | 671 | function TypedArrayJoin(separator) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 672 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 673 |  | 
|  | 674 | var length = %_TypedArrayGetLength(this); | 
|  | 675 |  | 
|  | 676 | return InnerArrayJoin(separator, this, length); | 
|  | 677 | } | 
|  | 678 |  | 
|  | 679 |  | 
|  | 680 | // ES6 draft 07-15-13, section 22.2.3.19 | 
|  | 681 | function TypedArrayReduce(callback, current) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 682 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 683 |  | 
|  | 684 | var length = %_TypedArrayGetLength(this); | 
|  | 685 | return InnerArrayReduce(callback, current, this, length, | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 686 | arguments.length); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 687 | } | 
|  | 688 | %FunctionSetLength(TypedArrayReduce, 1); | 
|  | 689 |  | 
|  | 690 |  | 
|  | 691 | // ES6 draft 07-15-13, section 22.2.3.19 | 
|  | 692 | function TypedArrayReduceRight(callback, current) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 693 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 694 |  | 
|  | 695 | var length = %_TypedArrayGetLength(this); | 
|  | 696 | return InnerArrayReduceRight(callback, current, this, length, | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 697 | arguments.length); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 698 | } | 
|  | 699 | %FunctionSetLength(TypedArrayReduceRight, 1); | 
|  | 700 |  | 
|  | 701 |  | 
|  | 702 | function TypedArraySlice(start, end) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 703 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 704 | var len = %_TypedArrayGetLength(this); | 
|  | 705 |  | 
|  | 706 | var relativeStart = TO_INTEGER(start); | 
|  | 707 |  | 
|  | 708 | var k; | 
|  | 709 | if (relativeStart < 0) { | 
|  | 710 | k = MaxSimple(len + relativeStart, 0); | 
|  | 711 | } else { | 
|  | 712 | k = MinSimple(relativeStart, len); | 
|  | 713 | } | 
|  | 714 |  | 
|  | 715 | var relativeEnd; | 
|  | 716 | if (IS_UNDEFINED(end)) { | 
|  | 717 | relativeEnd = len; | 
|  | 718 | } else { | 
|  | 719 | relativeEnd = TO_INTEGER(end); | 
|  | 720 | } | 
|  | 721 |  | 
|  | 722 | var final; | 
|  | 723 | if (relativeEnd < 0) { | 
|  | 724 | final = MaxSimple(len + relativeEnd, 0); | 
|  | 725 | } else { | 
|  | 726 | final = MinSimple(relativeEnd, len); | 
|  | 727 | } | 
|  | 728 |  | 
|  | 729 | var count = MaxSimple(final - k, 0); | 
|  | 730 | var array = TypedArraySpeciesCreate(this, count); | 
|  | 731 | // The code below is the 'then' branch; the 'else' branch species | 
|  | 732 | // a memcpy. Because V8 doesn't canonicalize NaN, the difference is | 
|  | 733 | // unobservable. | 
|  | 734 | var n = 0; | 
|  | 735 | while (k < final) { | 
|  | 736 | var kValue = this[k]; | 
|  | 737 | array[n] = kValue; | 
|  | 738 | k++; | 
|  | 739 | n++; | 
|  | 740 | } | 
|  | 741 | return array; | 
|  | 742 | } | 
|  | 743 |  | 
|  | 744 |  | 
|  | 745 | // ES2016 draft, section 22.2.3.14 | 
|  | 746 | function TypedArrayIncludes(searchElement, fromIndex) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 747 | if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 748 |  | 
|  | 749 | var length = %_TypedArrayGetLength(this); | 
|  | 750 |  | 
|  | 751 | return InnerArrayIncludes(searchElement, fromIndex, this, length); | 
|  | 752 | } | 
|  | 753 | %FunctionSetLength(TypedArrayIncludes, 1); | 
|  | 754 |  | 
|  | 755 |  | 
|  | 756 | // ES6 draft 08-24-14, section 22.2.2.2 | 
|  | 757 | function TypedArrayOf() { | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 758 | var length = arguments.length; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 759 | var array = TypedArrayCreate(this, length); | 
|  | 760 | for (var i = 0; i < length; i++) { | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 761 | array[i] = arguments[i]; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 762 | } | 
|  | 763 | return array; | 
|  | 764 | } | 
|  | 765 |  | 
|  | 766 |  | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 767 | // ES#sec-iterabletoarraylike Runtime Semantics: IterableToArrayLike( items ) | 
|  | 768 | function IterableToArrayLike(items) { | 
|  | 769 | var iterable = GetMethod(items, iteratorSymbol); | 
|  | 770 | if (!IS_UNDEFINED(iterable)) { | 
|  | 771 | var internal_array = new InternalArray(); | 
|  | 772 | var i = 0; | 
|  | 773 | for (var value of | 
|  | 774 | { [iteratorSymbol]() { return GetIterator(items, iterable) } }) { | 
|  | 775 | internal_array[i] = value; | 
|  | 776 | i++; | 
|  | 777 | } | 
|  | 778 | var array = []; | 
|  | 779 | %MoveArrayContents(internal_array, array); | 
|  | 780 | return array; | 
|  | 781 | } | 
|  | 782 | return TO_OBJECT(items); | 
|  | 783 | } | 
|  | 784 |  | 
|  | 785 |  | 
|  | 786 | // ES#sec-%typedarray%.from | 
|  | 787 | // %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] ) | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 788 | function TypedArrayFrom(source, mapfn, thisArg) { | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 789 | if (!%IsConstructor(this)) throw MakeTypeError(kNotConstructor, this); | 
|  | 790 | var mapping; | 
|  | 791 | if (!IS_UNDEFINED(mapfn)) { | 
|  | 792 | if (!IS_CALLABLE(mapfn)) throw MakeTypeError(kCalledNonCallable, this); | 
|  | 793 | mapping = true; | 
|  | 794 | } else { | 
|  | 795 | mapping = false; | 
|  | 796 | } | 
|  | 797 | var arrayLike = IterableToArrayLike(source); | 
|  | 798 | var length = TO_LENGTH(arrayLike.length); | 
|  | 799 | var targetObject = TypedArrayCreate(this, length); | 
|  | 800 | var value, mappedValue; | 
|  | 801 | for (var i = 0; i < length; i++) { | 
|  | 802 | value = arrayLike[i]; | 
|  | 803 | if (mapping) { | 
|  | 804 | mappedValue = %_Call(mapfn, thisArg, value, i); | 
|  | 805 | } else { | 
|  | 806 | mappedValue = value; | 
|  | 807 | } | 
|  | 808 | targetObject[i] = mappedValue; | 
|  | 809 | } | 
|  | 810 | return targetObject; | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 811 | } | 
|  | 812 | %FunctionSetLength(TypedArrayFrom, 1); | 
|  | 813 |  | 
|  | 814 | function TypedArray() { | 
|  | 815 | if (IS_UNDEFINED(new.target)) { | 
|  | 816 | throw MakeTypeError(kConstructorNonCallable, "TypedArray"); | 
|  | 817 | } | 
|  | 818 | if (new.target === TypedArray) { | 
|  | 819 | throw MakeTypeError(kConstructAbstractClass, "TypedArray"); | 
|  | 820 | } | 
|  | 821 | } | 
|  | 822 |  | 
|  | 823 | // ------------------------------------------------------------------- | 
|  | 824 |  | 
|  | 825 | %FunctionSetPrototype(TypedArray, new GlobalObject()); | 
|  | 826 | %AddNamedProperty(TypedArray.prototype, | 
|  | 827 | "constructor", TypedArray, DONT_ENUM); | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 828 | utils.InstallFunctions(TypedArray, DONT_ENUM, [ | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 829 | "from", TypedArrayFrom, | 
|  | 830 | "of", TypedArrayOf | 
|  | 831 | ]); | 
|  | 832 | utils.InstallGetter(TypedArray.prototype, "buffer", TypedArrayGetBuffer); | 
|  | 833 | utils.InstallGetter(TypedArray.prototype, "byteOffset", TypedArrayGetByteOffset, | 
|  | 834 | DONT_ENUM | DONT_DELETE); | 
|  | 835 | utils.InstallGetter(TypedArray.prototype, "byteLength", | 
|  | 836 | TypedArrayGetByteLength, DONT_ENUM | DONT_DELETE); | 
|  | 837 | utils.InstallGetter(TypedArray.prototype, "length", TypedArrayGetLength, | 
|  | 838 | DONT_ENUM | DONT_DELETE); | 
|  | 839 | utils.InstallGetter(TypedArray.prototype, toStringTagSymbol, | 
|  | 840 | TypedArrayGetToStringTag); | 
|  | 841 | utils.InstallFunctions(TypedArray.prototype, DONT_ENUM, [ | 
|  | 842 | "subarray", TypedArraySubArray, | 
|  | 843 | "set", TypedArraySet, | 
|  | 844 | "copyWithin", TypedArrayCopyWithin, | 
|  | 845 | "every", TypedArrayEvery, | 
|  | 846 | "fill", TypedArrayFill, | 
|  | 847 | "filter", TypedArrayFilter, | 
|  | 848 | "find", TypedArrayFind, | 
|  | 849 | "findIndex", TypedArrayFindIndex, | 
|  | 850 | "includes", TypedArrayIncludes, | 
|  | 851 | "indexOf", TypedArrayIndexOf, | 
|  | 852 | "join", TypedArrayJoin, | 
|  | 853 | "lastIndexOf", TypedArrayLastIndexOf, | 
|  | 854 | "forEach", TypedArrayForEach, | 
|  | 855 | "map", TypedArrayMap, | 
|  | 856 | "reduce", TypedArrayReduce, | 
|  | 857 | "reduceRight", TypedArrayReduceRight, | 
|  | 858 | "reverse", TypedArrayReverse, | 
|  | 859 | "slice", TypedArraySlice, | 
|  | 860 | "some", TypedArraySome, | 
|  | 861 | "sort", TypedArraySort, | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 862 | "toLocaleString", TypedArrayToLocaleString | 
|  | 863 | ]); | 
|  | 864 |  | 
| Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 865 | %AddNamedProperty(TypedArray.prototype, "toString", ArrayToString, | 
|  | 866 | DONT_ENUM); | 
|  | 867 |  | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 868 |  | 
|  | 869 | macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE) | 
|  | 870 | %SetCode(GlobalNAME, NAMEConstructor); | 
|  | 871 | %FunctionSetPrototype(GlobalNAME, new GlobalObject()); | 
|  | 872 | %InternalSetPrototype(GlobalNAME, TypedArray); | 
|  | 873 | %InternalSetPrototype(GlobalNAME.prototype, TypedArray.prototype); | 
|  | 874 |  | 
|  | 875 | %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE, | 
|  | 876 | READ_ONLY | DONT_ENUM | DONT_DELETE); | 
|  | 877 |  | 
|  | 878 | %AddNamedProperty(GlobalNAME.prototype, | 
|  | 879 | "constructor", global.NAME, DONT_ENUM); | 
|  | 880 | %AddNamedProperty(GlobalNAME.prototype, | 
|  | 881 | "BYTES_PER_ELEMENT", ELEMENT_SIZE, | 
|  | 882 | READ_ONLY | DONT_ENUM | DONT_DELETE); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 883 | endmacro | 
|  | 884 |  | 
|  | 885 | TYPED_ARRAYS(SETUP_TYPED_ARRAY) | 
|  | 886 |  | 
|  | 887 | // --------------------------- DataView ----------------------------- | 
|  | 888 |  | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 889 | function DataViewGetBufferJS() { | 
|  | 890 | if (!IS_DATAVIEW(this)) { | 
|  | 891 | throw MakeTypeError(kIncompatibleMethodReceiver, 'DataView.buffer', this); | 
|  | 892 | } | 
|  | 893 | return %DataViewGetBuffer(this); | 
|  | 894 | } | 
|  | 895 |  | 
|  | 896 | function DataViewGetByteOffset() { | 
|  | 897 | if (!IS_DATAVIEW(this)) { | 
|  | 898 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 899 | 'DataView.byteOffset', this); | 
|  | 900 | } | 
|  | 901 | return %_ArrayBufferViewGetByteOffset(this); | 
|  | 902 | } | 
|  | 903 |  | 
|  | 904 | function DataViewGetByteLength() { | 
|  | 905 | if (!IS_DATAVIEW(this)) { | 
|  | 906 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 907 | 'DataView.byteLength', this); | 
|  | 908 | } | 
|  | 909 | return %_ArrayBufferViewGetByteLength(this); | 
|  | 910 | } | 
|  | 911 |  | 
|  | 912 | macro DATA_VIEW_TYPES(FUNCTION) | 
|  | 913 | FUNCTION(Int8) | 
|  | 914 | FUNCTION(Uint8) | 
|  | 915 | FUNCTION(Int16) | 
|  | 916 | FUNCTION(Uint16) | 
|  | 917 | FUNCTION(Int32) | 
|  | 918 | FUNCTION(Uint32) | 
|  | 919 | FUNCTION(Float32) | 
|  | 920 | FUNCTION(Float64) | 
|  | 921 | endmacro | 
|  | 922 |  | 
|  | 923 |  | 
|  | 924 | macro DATA_VIEW_GETTER_SETTER(TYPENAME) | 
|  | 925 | function DataViewGetTYPENAMEJS(offset, little_endian) { | 
|  | 926 | if (!IS_DATAVIEW(this)) { | 
|  | 927 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 928 | 'DataView.getTYPENAME', this); | 
|  | 929 | } | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 930 | if (arguments.length < 1) throw MakeTypeError(kInvalidArgument); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 931 | offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset); | 
|  | 932 | return %DataViewGetTYPENAME(this, offset, !!little_endian); | 
|  | 933 | } | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 934 | %FunctionSetLength(DataViewGetTYPENAMEJS, 1); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 935 |  | 
|  | 936 | function DataViewSetTYPENAMEJS(offset, value, little_endian) { | 
|  | 937 | if (!IS_DATAVIEW(this)) { | 
|  | 938 | throw MakeTypeError(kIncompatibleMethodReceiver, | 
|  | 939 | 'DataView.setTYPENAME', this); | 
|  | 940 | } | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 941 | if (arguments.length < 2) throw MakeTypeError(kInvalidArgument); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 942 | offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset); | 
|  | 943 | %DataViewSetTYPENAME(this, offset, TO_NUMBER(value), !!little_endian); | 
|  | 944 | } | 
| Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 945 | %FunctionSetLength(DataViewSetTYPENAMEJS, 2); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 946 | endmacro | 
|  | 947 |  | 
|  | 948 | DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER) | 
|  | 949 |  | 
|  | 950 | // Setup the DataView constructor. | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 951 | %FunctionSetPrototype(GlobalDataView, new GlobalObject); | 
|  | 952 |  | 
|  | 953 | // Set up constructor property on the DataView prototype. | 
|  | 954 | %AddNamedProperty(GlobalDataView.prototype, "constructor", GlobalDataView, | 
|  | 955 | DONT_ENUM); | 
|  | 956 | %AddNamedProperty(GlobalDataView.prototype, toStringTagSymbol, "DataView", | 
|  | 957 | READ_ONLY|DONT_ENUM); | 
|  | 958 |  | 
|  | 959 | utils.InstallGetter(GlobalDataView.prototype, "buffer", DataViewGetBufferJS); | 
|  | 960 | utils.InstallGetter(GlobalDataView.prototype, "byteOffset", | 
|  | 961 | DataViewGetByteOffset); | 
|  | 962 | utils.InstallGetter(GlobalDataView.prototype, "byteLength", | 
|  | 963 | DataViewGetByteLength); | 
|  | 964 |  | 
|  | 965 | utils.InstallFunctions(GlobalDataView.prototype, DONT_ENUM, [ | 
|  | 966 | "getInt8", DataViewGetInt8JS, | 
|  | 967 | "setInt8", DataViewSetInt8JS, | 
|  | 968 |  | 
|  | 969 | "getUint8", DataViewGetUint8JS, | 
|  | 970 | "setUint8", DataViewSetUint8JS, | 
|  | 971 |  | 
|  | 972 | "getInt16", DataViewGetInt16JS, | 
|  | 973 | "setInt16", DataViewSetInt16JS, | 
|  | 974 |  | 
|  | 975 | "getUint16", DataViewGetUint16JS, | 
|  | 976 | "setUint16", DataViewSetUint16JS, | 
|  | 977 |  | 
|  | 978 | "getInt32", DataViewGetInt32JS, | 
|  | 979 | "setInt32", DataViewSetInt32JS, | 
|  | 980 |  | 
|  | 981 | "getUint32", DataViewGetUint32JS, | 
|  | 982 | "setUint32", DataViewSetUint32JS, | 
|  | 983 |  | 
|  | 984 | "getFloat32", DataViewGetFloat32JS, | 
|  | 985 | "setFloat32", DataViewSetFloat32JS, | 
|  | 986 |  | 
|  | 987 | "getFloat64", DataViewGetFloat64JS, | 
|  | 988 | "setFloat64", DataViewSetFloat64JS | 
|  | 989 | ]); | 
|  | 990 |  | 
|  | 991 | }) |