| /* |
| * Copyright (C) 2015-2016 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| // Note that the intrisic @typedArrayLength checks that the argument passed is a typed array |
| // and throws if it is not. |
| |
| |
| // Typed Arrays have their own species constructor function since they need |
| // to look up their default constructor, which is expensive. If we used the |
| // normal speciesConstructor helper we would need to look up the default |
| // constructor every time. |
| @globalPrivate |
| function typedArraySpeciesConstructor(value) |
| { |
| "use strict"; |
| let constructor = value.constructor; |
| if (constructor === @undefined) |
| return @typedArrayGetOriginalConstructor(value); |
| |
| if (!@isObject(constructor)) |
| @throwTypeError("|this|.constructor is not an Object or undefined"); |
| |
| constructor = constructor.@speciesSymbol; |
| if (@isUndefinedOrNull(constructor)) |
| return @typedArrayGetOriginalConstructor(value); |
| // The lack of an @isConstructor(constructor) check here is not observable because |
| // the first thing we will do with the value is attempt to construct the result with it. |
| // If any user of this function does not immediately construct the result they need to |
| // verify that the result is a constructor. |
| return constructor; |
| } |
| |
| @globalPrivate |
| function typedArrayClampArgumentToStartOrEnd(value, length, undefinedValue) |
| { |
| "use strict"; |
| |
| if (value === @undefined) |
| return undefinedValue; |
| |
| let int = @toInteger(value); |
| if (int < 0) { |
| int += length; |
| return int < 0 ? 0 : int; |
| } |
| return int > length ? length : int; |
| } |
| |
| function values() |
| { |
| "use strict"; |
| @typedArrayLength(this); |
| return new @ArrayIterator(this, "value", @arrayIteratorValueNext); |
| } |
| |
| function keys() |
| { |
| "use strict"; |
| @typedArrayLength(this); |
| return new @ArrayIterator(this, "key", @arrayIteratorKeyNext); |
| } |
| |
| function entries() |
| { |
| "use strict"; |
| @typedArrayLength(this); |
| return new @ArrayIterator(this, "key+value", @arrayIteratorKeyValueNext); |
| } |
| |
| function every(callback /*, thisArg */) |
| { |
| "use strict"; |
| var length = @typedArrayLength(this); |
| var thisArg = @argument(1); |
| |
| if (typeof callback !== "function") |
| @throwTypeError("TypedArray.prototype.every callback must be a function"); |
| |
| for (var i = 0; i < length; i++) { |
| if (!callback.@call(thisArg, this[i], i, this)) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| function fill(value /* [, start [, end]] */) |
| { |
| "use strict"; |
| |
| let length = @typedArrayLength(this); |
| |
| let start = @argument(1); |
| let end = @argument(2); |
| |
| start = @typedArrayClampArgumentToStartOrEnd(start, length, 0); |
| end = @typedArrayClampArgumentToStartOrEnd(end, length, length); |
| |
| for (let i = start; i < end; i++) |
| this[i] = value; |
| return this; |
| } |
| |
| function find(callback /* [, thisArg] */) |
| { |
| "use strict"; |
| var length = @typedArrayLength(this); |
| var thisArg = @argument(1); |
| |
| if (typeof callback !== "function") |
| @throwTypeError("TypedArray.prototype.find callback must be a function"); |
| |
| for (var i = 0; i < length; i++) { |
| let elem = this[i]; |
| if (callback.@call(thisArg, elem, i, this)) |
| return elem; |
| } |
| return @undefined; |
| } |
| |
| function findIndex(callback /* [, thisArg] */) |
| { |
| "use strict"; |
| var length = @typedArrayLength(this); |
| var thisArg = @argument(1); |
| |
| if (typeof callback !== "function") |
| @throwTypeError("TypedArray.prototype.findIndex callback must be a function"); |
| |
| for (var i = 0; i < length; i++) { |
| if (callback.@call(thisArg, this[i], i, this)) |
| return i; |
| } |
| return -1; |
| } |
| |
| function forEach(callback /* [, thisArg] */) |
| { |
| "use strict"; |
| var length = @typedArrayLength(this); |
| var thisArg = @argument(1); |
| |
| if (typeof callback !== "function") |
| @throwTypeError("TypedArray.prototype.forEach callback must be a function"); |
| |
| for (var i = 0; i < length; i++) |
| callback.@call(thisArg, this[i], i, this); |
| } |
| |
| function some(callback /* [, thisArg] */) |
| { |
| // 22.2.3.24 |
| "use strict"; |
| var length = @typedArrayLength(this); |
| var thisArg = @argument(1); |
| |
| if (typeof callback !== "function") |
| @throwTypeError("TypedArray.prototype.some callback must be a function"); |
| |
| for (var i = 0; i < length; i++) { |
| if (callback.@call(thisArg, this[i], i, this)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| function sort(comparator) |
| { |
| // 22.2.3.25 |
| "use strict"; |
| |
| function min(a, b) |
| { |
| return a < b ? a : b; |
| } |
| |
| function merge(dst, src, srcIndex, srcEnd, width, comparator) |
| { |
| var left = srcIndex; |
| var leftEnd = min(left + width, srcEnd); |
| var right = leftEnd; |
| var rightEnd = min(right + width, srcEnd); |
| |
| for (var dstIndex = left; dstIndex < rightEnd; ++dstIndex) { |
| if (right < rightEnd) { |
| if (left >= leftEnd || comparator(src[right], src[left]) < 0) { |
| dst[dstIndex] = src[right++]; |
| continue; |
| } |
| } |
| |
| dst[dstIndex] = src[left++]; |
| } |
| } |
| |
| function mergeSort(array, valueCount, comparator) |
| { |
| var buffer = [ ]; |
| buffer.length = valueCount; |
| |
| var dst = buffer; |
| var src = array; |
| |
| for (var width = 1; width < valueCount; width *= 2) { |
| for (var srcIndex = 0; srcIndex < valueCount; srcIndex += 2 * width) |
| merge(dst, src, srcIndex, valueCount, width, comparator); |
| |
| var tmp = src; |
| src = dst; |
| dst = tmp; |
| } |
| |
| if (src != array) { |
| for(var i = 0; i < valueCount; i++) |
| array[i] = src[i]; |
| } |
| } |
| |
| var length = @typedArrayLength(this); |
| |
| if (length < 2) |
| return; |
| |
| if (typeof comparator == "function") |
| mergeSort(this, length, comparator); |
| else |
| @typedArraySort(this); |
| |
| return this; |
| } |
| |
| function subarray(begin, end) |
| { |
| "use strict"; |
| |
| if (!@isTypedArrayView(this)) |
| @throwTypeError("|this| should be a typed array view"); |
| |
| let start = @toInteger(begin); |
| let finish; |
| if (end !== @undefined) |
| finish = @toInteger(end); |
| |
| let constructor = @typedArraySpeciesConstructor(this); |
| |
| return @typedArraySubarrayCreate.@call(this, start, finish, constructor); |
| } |
| |
| function reduce(callback /* [, initialValue] */) |
| { |
| // 22.2.3.19 |
| "use strict"; |
| |
| var length = @typedArrayLength(this); |
| |
| if (typeof callback !== "function") |
| @throwTypeError("TypedArray.prototype.reduce callback must be a function"); |
| |
| var argumentCount = @argumentCount(); |
| if (length === 0 && argumentCount < 2) |
| @throwTypeError("TypedArray.prototype.reduce of empty array with no initial value"); |
| |
| var accumulator, k = 0; |
| if (argumentCount > 1) |
| accumulator = @argument(1); |
| else |
| accumulator = this[k++]; |
| |
| for (; k < length; k++) |
| accumulator = callback.@call(@undefined, accumulator, this[k], k, this); |
| |
| return accumulator; |
| } |
| |
| function reduceRight(callback /* [, initialValue] */) |
| { |
| // 22.2.3.20 |
| "use strict"; |
| |
| var length = @typedArrayLength(this); |
| |
| if (typeof callback !== "function") |
| @throwTypeError("TypedArray.prototype.reduceRight callback must be a function"); |
| |
| var argumentCount = @argumentCount(); |
| if (length === 0 && argumentCount < 2) |
| @throwTypeError("TypedArray.prototype.reduceRight of empty array with no initial value"); |
| |
| var accumulator, k = length - 1; |
| if (argumentCount > 1) |
| accumulator = @argument(1); |
| else |
| accumulator = this[k--]; |
| |
| for (; k >= 0; k--) |
| accumulator = callback.@call(@undefined, accumulator, this[k], k, this); |
| |
| return accumulator; |
| } |
| |
| function map(callback /*, thisArg */) |
| { |
| // 22.2.3.18 |
| "use strict"; |
| |
| var length = @typedArrayLength(this); |
| |
| if (typeof callback !== "function") |
| @throwTypeError("TypedArray.prototype.map callback must be a function"); |
| |
| var thisArg = @argument(1); |
| |
| // Do species construction |
| var constructor = this.constructor; |
| var result; |
| if (constructor === @undefined) |
| result = new (@typedArrayGetOriginalConstructor(this))(length); |
| else { |
| var speciesConstructor = constructor.@speciesSymbol; |
| if (@isUndefinedOrNull(speciesConstructor)) |
| result = new (@typedArrayGetOriginalConstructor(this))(length); |
| else { |
| result = new speciesConstructor(length); |
| // typedArrayLength throws if it doesn't get a view. |
| @typedArrayLength(result); |
| } |
| } |
| |
| for (var i = 0; i < length; i++) { |
| var mappedValue = callback.@call(thisArg, this[i], i, this); |
| result[i] = mappedValue; |
| } |
| return result; |
| } |
| |
| function filter(callback /*, thisArg */) |
| { |
| "use strict"; |
| |
| var length = @typedArrayLength(this); |
| |
| if (typeof callback !== "function") |
| @throwTypeError("TypedArray.prototype.filter callback must be a function"); |
| |
| var thisArg = @argument(1); |
| var kept = []; |
| |
| for (var i = 0; i < length; i++) { |
| var value = this[i]; |
| if (callback.@call(thisArg, value, i, this)) |
| kept.@push(value); |
| } |
| |
| var constructor = this.constructor; |
| var result; |
| var resultLength = kept.length; |
| if (constructor === @undefined) |
| result = new (@typedArrayGetOriginalConstructor(this))(resultLength); |
| else { |
| var speciesConstructor = constructor.@speciesSymbol; |
| if (@isUndefinedOrNull(speciesConstructor)) |
| result = new (@typedArrayGetOriginalConstructor(this))(resultLength); |
| else { |
| result = new speciesConstructor(resultLength); |
| // typedArrayLength throws if it doesn't get a view. |
| @typedArrayLength(result); |
| } |
| } |
| |
| for (var i = 0; i < kept.length; i++) |
| result[i] = kept[i]; |
| |
| return result; |
| } |
| |
| function toLocaleString(/* locale, options */) |
| { |
| "use strict"; |
| |
| var length = @typedArrayLength(this); |
| |
| if (length == 0) |
| return ""; |
| |
| var string = this[0].toLocaleString(@argument(0), @argument(1)); |
| for (var i = 1; i < length; i++) |
| string += "," + this[i].toLocaleString(@argument(0), @argument(1)); |
| |
| return string; |
| } |