diff --git a/js/src/builtin/TypedArray.js b/js/src/builtin/TypedArray.js index d1d4869ed320..1df7b8039812 100644 --- a/js/src/builtin/TypedArray.js +++ b/js/src/builtin/TypedArray.js @@ -749,6 +749,52 @@ function TypedArraySome(callbackfn, thisArg = undefined) { return false; } +// ES6 draft 20150304 %TypedArray%.prototype.subarray +function TypedArraySubarray(begin, end) { + // Step 1. + var obj = this; + + // Steps 2-3. + // This function is not generic. + if (!IsObject(obj) || !IsTypedArray(obj)) { + return callFunction(CallTypedArrayMethodIfWrapped, this, begin, end, + "TypedArraySubarray"); + } + + // Steps 4-6. + var buffer = TypedArrayBuffer(obj); + var srcLength = TypedArrayLength(obj); + + // Steps 7-9. + var relativeBegin = ToInteger(begin); + var beginIndex = relativeBegin < 0 ? std_Math_max(srcLength + relativeBegin, 0) + : std_Math_min(relativeBegin, srcLength); + + // Steps 10-12. + var relativeEnd = end === undefined ? srcLength : ToInteger(end); + var endIndex = relativeEnd < 0 ? std_Math_max(srcLength + relativeEnd, 0) + : std_Math_min(relativeEnd, srcLength); + + // Step 13. + var newLength = std_Math_max(endIndex - beginIndex, 0); + + // Steps 14-15, altered to use a shift instead of a size for performance. + var elementShift = TypedArrayElementShift(obj); + + // Step 16. + var srcByteOffset = TypedArrayByteOffset(obj); + + // Step 17. + var beginByteOffset = srcByteOffset + (beginIndex << elementShift); + + // Steps 18-20. + var defaultConstructor = _ConstructorForTypedArray(obj); + var constructor = SpeciesConstructor(obj, defaultConstructor); + + // Steps 21-22. + return new constructor(buffer, beginByteOffset, newLength); +} + // ES6 draft rev30 (2014/12/24) 22.2.3.30 %TypedArray%.prototype.values() function TypedArrayValues() { // Step 1. diff --git a/js/src/vm/TypedArrayCommon.h b/js/src/vm/TypedArrayCommon.h index 4e590a46c8d6..120ed8963018 100644 --- a/js/src/vm/TypedArrayCommon.h +++ b/js/src/vm/TypedArrayCommon.h @@ -481,7 +481,12 @@ class TypedArrayMethods typedef typename SomeTypedArray::template OfType::Type Uint8ClampedArrayType; public: - /* subarray(start[, end]) */ + // subarray(start[, end]) + // %TypedArray%.prototype.subarray is a self-hosted method, so this code is + // only used for shared typed arrays. We should self-host both methods + // eventually (but note TypedArraySubarray will require changes to be used + // with shared typed arrays), but we need to rejigger the shared typed + // array prototype chain before we can do that. static bool subarray(JSContext *cx, CallArgs args) { diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index a897d023f27c..4146dd648cd2 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -779,17 +779,9 @@ TypedArrayObject::set(JSContext *cx, unsigned argc, Value *vp) TypedArrayMethods::set>(cx, args); } -/* static */ bool -TypedArrayObject::subarray(JSContext *cx, unsigned argc, Value *vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod::subarray>(cx, args); -} - /* static */ const JSFunctionSpec TypedArrayObject::protoFunctions[] = { - JS_FN("subarray", TypedArrayObject::subarray, 2, 0), + JS_SELF_HOSTED_FN("subarray", "TypedArraySubarray", 2, 0), JS_FN("set", TypedArrayObject::set, 2, 0), JS_SELF_HOSTED_FN("copyWithin", "TypedArrayCopyWithin", 3, 0), JS_SELF_HOSTED_FN("every", "TypedArrayEvery", 2, 0), diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h index b7ca32114ac2..56efda225d9f 100644 --- a/js/src/vm/TypedArrayObject.h +++ b/js/src/vm/TypedArrayObject.h @@ -215,7 +215,6 @@ class TypedArrayObject : public NativeObject static bool is(HandleValue v); static bool set(JSContext *cx, unsigned argc, Value *vp); - static bool subarray(JSContext *cx, unsigned argc, Value *vp); }; inline bool