diff --git a/js/src/builtin/TypedArray.js b/js/src/builtin/TypedArray.js index f51081d84f40..574120df55d7 100644 --- a/js/src/builtin/TypedArray.js +++ b/js/src/builtin/TypedArray.js @@ -2,6 +2,45 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// ES6 draft rev29 (2014/12/06) 22.2.3.8 %TypedArray%.prototype.fill(value [, start [, end ]]) +function TypedArrayFill(value, start = 0, end = undefined) { + // This function is not generic. + if (!IsObject(this) || !IsTypedArray(this)) { + return callFunction(CallTypedArrayMethodIfWrapped, this, value, start, end, + "TypedArrayFill"); + } + + // Steps 1-2. + var O = this; + + // Steps 3-5. + var len = TypedArrayLength(O); + + // Steps 6-7. + var relativeStart = ToInteger(start); + + // Step 8. + var k = relativeStart < 0 + ? std_Math_max(len + relativeStart, 0) + : std_Math_min(relativeStart, len); + + // Steps 9-10. + var relativeEnd = end === undefined ? len : ToInteger(end); + + // Step 11. + var final = relativeEnd < 0 + ? std_Math_max(len + relativeEnd, 0) + : std_Math_min(relativeEnd, len); + + // Step 12. + for (; k < final; k++) { + O[k] = value; + } + + // Step 13. + return O; +} + // ES6 draft rev28 (2014/10/14) 22.2.3.10 %TypedArray%.prototype.find(predicate[, thisArg]). function TypedArrayFind(predicate, thisArg = undefined) { // This function is not generic. diff --git a/js/src/tests/ecma_6/TypedArray/fill.js b/js/src/tests/ecma_6/TypedArray/fill.js new file mode 100644 index 000000000000..9093239c89d5 --- /dev/null +++ b/js/src/tests/ecma_6/TypedArray/fill.js @@ -0,0 +1,77 @@ +const constructors = [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array +]; + +for (var constructor of constructors) { + assertDeepEq(constructor.prototype.fill.length, 1); + + assertDeepEq(new constructor([]).fill(1), new constructor([])); + assertDeepEq(new constructor([1,1,1]).fill(2), new constructor([2,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, 1), new constructor([1,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, 1, 2), new constructor([1,2,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, -2), new constructor([1,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, -2, -1), new constructor([1,2,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, undefined), new constructor([2,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, undefined, undefined), new constructor([2,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, 1, undefined), new constructor([1,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, undefined, 1), new constructor([2,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, 2, 1), new constructor([1,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, -1, 1), new constructor([1,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, -2, 1), new constructor([1,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, 1, -2), new constructor([1,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, 0.1), new constructor([2,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, 0.9), new constructor([2,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, 1.1), new constructor([1,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, 0.1, 0.9), new constructor([1,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, 0.1, 1.9), new constructor([2,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, 0.1, 1.9), new constructor([2,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, -0), new constructor([2,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, 0, -0), new constructor([1,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, NaN), new constructor([2,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, 0, NaN), new constructor([1,1,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, false), new constructor([2,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, true), new constructor([1,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, "0"), new constructor([2,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, "1"), new constructor([1,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, "-2"), new constructor([1,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, "-2", "-1"), new constructor([1,2,1])); + assertDeepEq(new constructor([1,1,1]).fill(2, {valueOf: ()=>1}), new constructor([1,2,2])); + assertDeepEq(new constructor([1,1,1]).fill(2, 0, {valueOf: ()=>1}), new constructor([2,1,1])); + + // Called from other globals. + if (typeof newGlobal === "function") { + var fill = newGlobal()[constructor.name].prototype.fill; + assertDeepEq(fill.call(new constructor([3, 2, 1]), 2), new constructor([2, 2, 2])); + } + + // Throws if `this` isn't a TypedArray. + var nonTypedArrays = [undefined, null, 1, false, "", Symbol(), [], {}, /./, + /* new Proxy(new constructor(), {}) // This probably should throw */ + ]; + nonTypedArrays.forEach(nonTypedArray => { + assertThrowsInstanceOf(function() { + constructor.prototype.fill.call(nonTypedArray, 1); + }, TypeError); + }); + + // Test that the length getter is never called. + Object.defineProperty(new constructor([1, 2, 3]), "length", { + get() { + throw new Error("length accessor called"); + } + }).fill(1); +} + +assertDeepEq(new Float32Array([0, 0]).fill(NaN), new Float32Array([NaN, NaN])); +assertDeepEq(new Float64Array([0, 0]).fill(NaN), new Float64Array([NaN, NaN])); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 5c1b7c16b321..9ef703c055cd 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -781,6 +781,7 @@ TypedArrayObject::protoFunctions[] = { JS_FN("subarray", TypedArrayObject::subarray, 2, 0), JS_FN("set", TypedArrayObject::set, 2, 0), JS_FN("copyWithin", TypedArrayObject::copyWithin, 2, 0), + JS_SELF_HOSTED_FN("fill", "TypedArrayFill", 3, 0), JS_SELF_HOSTED_FN("find", "TypedArrayFind", 2, 0), JS_SELF_HOSTED_FN("findIndex", "TypedArrayFindIndex", 2, 0), JS_SELF_HOSTED_FN("indexOf", "TypedArrayIndexOf", 2, 0),