8165c816286b0d089c71085cc81b616e61e7821c
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSGenericTypedArrayViewPrototypeFunctions.h
1 /*
2  * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "ArrayPrototype.h"
29 #include "Error.h"
30 #include "ExceptionHelpers.h"
31 #include "JSArrayBufferViewInlines.h"
32 #include "JSCBuiltins.h"
33 #include "JSCJSValueInlines.h"
34 #include "JSFunction.h"
35 #include "JSGenericTypedArrayViewInlines.h"
36 #include "JSGenericTypedArrayViewPrototypeInlines.h"
37 #include "JSStringJoiner.h"
38 #include "StructureInlines.h"
39 #include "TypedArrayAdaptors.h"
40 #include <wtf/StdLibExtras.h>
41
42 namespace JSC {
43
44 // This implements 22.2.4.7 TypedArraySpeciesCreate
45 // Note, that this function throws.
46 template<typename Functor>
47 inline JSArrayBufferView* speciesConstruct(ExecState* exec, JSObject* exemplar, MarkedArgumentBuffer& args, const Functor& defaultConstructor)
48 {
49     VM& vm = exec->vm();
50     auto scope = DECLARE_THROW_SCOPE(vm);
51
52     JSValue constructor = exemplar->get(exec, exec->propertyNames().constructor);
53     RETURN_IF_EXCEPTION(scope, nullptr);
54
55     if (constructor.isUndefined())
56         return defaultConstructor();
57     if (!constructor.isObject()) {
58         throwTypeError(exec, scope, ASCIILiteral("constructor Property should not be null"));
59         return nullptr;
60     }
61
62     JSValue species = constructor.get(exec, exec->propertyNames().speciesSymbol);
63     RETURN_IF_EXCEPTION(scope, nullptr);
64
65     if (species.isUndefinedOrNull())
66         return defaultConstructor();
67
68     JSValue result = construct(exec, species, args, "species is not a constructor");
69     RETURN_IF_EXCEPTION(scope, nullptr);
70
71     if (JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(result)) {
72         if (!view->isNeutered())
73             return view;
74
75         throwTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
76         return nullptr;
77     }
78
79     throwTypeError(exec, scope, ASCIILiteral("species constructor did not return a TypedArray View"));
80     return nullptr;
81 }
82
83 inline unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)
84 {
85     JSValue value = exec->argument(argument);
86     if (value.isUndefined())
87         return undefinedValue;
88
89     double indexDouble = value.toInteger(exec);
90     if (indexDouble < 0) {
91         indexDouble += length;
92         return indexDouble < 0 ? 0 : static_cast<unsigned>(indexDouble);
93     }
94     return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
95 }
96
97 template<typename ViewClass>
98 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncSet(VM& vm, ExecState* exec)
99 {
100     auto scope = DECLARE_THROW_SCOPE(vm);
101
102     // 22.2.3.22
103     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
104
105     if (UNLIKELY(!exec->argumentCount()))
106         return throwVMTypeError(exec, scope, ASCIILiteral("Expected at least one argument"));
107
108     unsigned offset;
109     if (exec->argumentCount() >= 2) {
110         double offsetNumber = exec->uncheckedArgument(1).toInteger(exec);
111         RETURN_IF_EXCEPTION(scope, encodedJSValue());
112         if (UNLIKELY(offsetNumber < 0))
113             return throwVMRangeError(exec, scope, "Offset should not be negative");
114         offset = static_cast<unsigned>(std::min(offsetNumber, static_cast<double>(std::numeric_limits<unsigned>::max())));
115     } else
116         offset = 0;
117
118     if (UNLIKELY(thisObject->isNeutered()))
119         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
120
121     JSObject* sourceArray = jsDynamicCast<JSObject*>(exec->uncheckedArgument(0));
122     if (UNLIKELY(!sourceArray))
123         return throwVMTypeError(exec, scope, ASCIILiteral("First argument should be an object"));
124
125     unsigned length;
126     if (isTypedView(sourceArray->classInfo()->typedArrayStorageType)) {
127         JSArrayBufferView* sourceView = jsCast<JSArrayBufferView*>(sourceArray);
128         if (UNLIKELY(sourceView->isNeutered()))
129             return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
130
131         length = jsCast<JSArrayBufferView*>(sourceArray)->length();
132     } else
133         length = sourceArray->get(exec, vm.propertyNames->length).toUInt32(exec);
134
135     RETURN_IF_EXCEPTION(scope, encodedJSValue());
136
137     thisObject->set(exec, offset, sourceArray, 0, length, CopyType::Unobservable);
138     return JSValue::encode(jsUndefined());
139 }
140
141 template<typename ViewClass>
142 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncCopyWithin(VM& vm, ExecState* exec)
143 {
144     auto scope = DECLARE_THROW_SCOPE(vm);
145
146     // 22.2.3.5
147     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
148     if (thisObject->isNeutered())
149         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
150
151     long length = thisObject->length();
152     long to = argumentClampedIndexFromStartOrEnd(exec, 0, length);
153     RETURN_IF_EXCEPTION(scope, encodedJSValue());
154     long from = argumentClampedIndexFromStartOrEnd(exec, 1, length);
155     RETURN_IF_EXCEPTION(scope, encodedJSValue());
156     long final = argumentClampedIndexFromStartOrEnd(exec, 2, length, length);
157     RETURN_IF_EXCEPTION(scope, encodedJSValue());
158
159     if (final < from)
160         return JSValue::encode(exec->thisValue());
161
162     long count = std::min(length - std::max(to, from), final - from);
163
164     if (thisObject->isNeutered())
165         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
166
167     typename ViewClass::ElementType* array = thisObject->typedVector();
168     memmove(array + to, array + from, count * thisObject->elementSize);
169
170     return JSValue::encode(exec->thisValue());
171 }
172
173 template<typename ViewClass>
174 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncIncludes(VM& vm, ExecState* exec)
175 {
176     auto scope = DECLARE_THROW_SCOPE(vm);
177
178     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
179     if (thisObject->isNeutered())
180         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
181
182     unsigned length = thisObject->length();
183
184     if (!length)
185         return JSValue::encode(jsBoolean(false));
186
187     JSValue valueToFind = exec->argument(0);
188
189     unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
190     RETURN_IF_EXCEPTION(scope, encodedJSValue());
191
192     if (thisObject->isNeutered())
193         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
194
195     typename ViewClass::ElementType* array = thisObject->typedVector();
196     auto targetOption = ViewClass::toAdaptorNativeFromValueWithoutCoercion(valueToFind);
197     if (!targetOption)
198         return JSValue::encode(jsBoolean(false));
199
200     ASSERT(!scope.exception());
201     RELEASE_ASSERT(!thisObject->isNeutered());
202
203     if (std::isnan(static_cast<double>(*targetOption))) {
204         for (; index < length; ++index) {
205             if (std::isnan(static_cast<double>(array[index])))
206                 return JSValue::encode(jsBoolean(true));
207         }
208     } else {
209         for (; index < length; ++index) {
210             if (array[index] == targetOption)
211                 return JSValue::encode(jsBoolean(true));
212         }
213     }
214
215     return JSValue::encode(jsBoolean(false));
216 }
217
218 template<typename ViewClass>
219 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncIndexOf(VM& vm, ExecState* exec)
220 {
221     auto scope = DECLARE_THROW_SCOPE(vm);
222
223     // 22.2.3.13
224     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
225     if (thisObject->isNeutered())
226         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
227
228     if (!exec->argumentCount())
229         return throwVMTypeError(exec, scope, ASCIILiteral("Expected at least one argument"));
230
231     unsigned length = thisObject->length();
232
233     JSValue valueToFind = exec->argument(0);
234     unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
235     RETURN_IF_EXCEPTION(scope, encodedJSValue());
236
237     if (thisObject->isNeutered())
238         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
239
240     typename ViewClass::ElementType* array = thisObject->typedVector();
241     auto targetOption = ViewClass::toAdaptorNativeFromValueWithoutCoercion(valueToFind);
242     if (!targetOption)
243         return JSValue::encode(jsNumber(-1));
244     ASSERT(!scope.exception());
245     RELEASE_ASSERT(!thisObject->isNeutered());
246
247     for (; index < length; ++index) {
248         if (array[index] == targetOption)
249             return JSValue::encode(jsNumber(index));
250     }
251
252     return JSValue::encode(jsNumber(-1));
253 }
254
255 template<typename ViewClass>
256 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncJoin(VM& vm, ExecState* exec)
257 {
258     auto scope = DECLARE_THROW_SCOPE(vm);
259
260     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
261     if (thisObject->isNeutered())
262         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
263
264     // 22.2.3.14
265     auto joinWithSeparator = [&] (StringView separator) -> EncodedJSValue {
266         ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
267         unsigned length = thisObject->length();
268
269         JSStringJoiner joiner(*exec, separator, length);
270         RETURN_IF_EXCEPTION(scope, encodedJSValue());
271         for (unsigned i = 0; i < length; i++) {
272             joiner.append(*exec, thisObject->getIndexQuickly(i));
273             RETURN_IF_EXCEPTION(scope, encodedJSValue());
274         }
275         return JSValue::encode(joiner.join(*exec));
276     };
277
278     JSValue separatorValue = exec->argument(0);
279     if (separatorValue.isUndefined()) {
280         const LChar* comma = reinterpret_cast<const LChar*>(",");
281         return joinWithSeparator({ comma, 1 });
282     }
283
284     JSString* separatorString = separatorValue.toString(exec);
285     RETURN_IF_EXCEPTION(scope, encodedJSValue());
286
287     if (thisObject->isNeutered())
288         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
289     return joinWithSeparator(separatorString->view(exec).get());
290 }
291
292 template<typename ViewClass>
293 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncLastIndexOf(VM& vm, ExecState* exec)
294 {
295     auto scope = DECLARE_THROW_SCOPE(vm);
296
297     // 22.2.3.16
298     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
299     if (thisObject->isNeutered())
300         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
301
302     if (!exec->argumentCount())
303         return throwVMTypeError(exec, scope, ASCIILiteral("Expected at least one argument"));
304
305     unsigned length = thisObject->length();
306
307     JSValue valueToFind = exec->argument(0);
308
309     int index = length - 1;
310     if (exec->argumentCount() >= 2) {
311         JSValue fromValue = exec->uncheckedArgument(1);
312         double fromDouble = fromValue.toInteger(exec);
313         if (fromDouble < 0) {
314             fromDouble += length;
315             if (fromDouble < 0)
316                 return JSValue::encode(jsNumber(-1));
317         }
318         if (fromDouble < length)
319             index = static_cast<unsigned>(fromDouble);
320     }
321
322     RETURN_IF_EXCEPTION(scope, encodedJSValue());
323
324     if (thisObject->isNeutered())
325         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
326
327     auto targetOption = ViewClass::toAdaptorNativeFromValueWithoutCoercion(valueToFind);
328     if (!targetOption)
329         return JSValue::encode(jsNumber(-1));
330
331     typename ViewClass::ElementType* array = thisObject->typedVector();
332     ASSERT(!scope.exception());
333     RELEASE_ASSERT(!thisObject->isNeutered());
334
335     for (; index >= 0; --index) {
336         if (array[index] == targetOption)
337             return JSValue::encode(jsNumber(index));
338     }
339
340     return JSValue::encode(jsNumber(-1));
341 }
342
343 template<typename ViewClass>
344 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoGetterFuncBuffer(VM&, ExecState* exec)
345 {
346     // 22.2.3.3
347     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
348
349     return JSValue::encode(thisObject->jsBuffer(exec));
350 }
351
352 template<typename ViewClass>
353 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoGetterFuncLength(VM&, ExecState* exec)
354 {
355     // 22.2.3.17
356     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
357
358     return JSValue::encode(jsNumber(thisObject->length()));
359 }
360
361 template<typename ViewClass>
362 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoGetterFuncByteLength(VM&, ExecState* exec)
363 {
364     // 22.2.3.2
365     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
366
367     return JSValue::encode(jsNumber(thisObject->byteLength()));
368 }
369
370 template<typename ViewClass>
371 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoGetterFuncByteOffset(VM&, ExecState* exec)
372 {
373     // 22.2.3.3
374     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
375
376     return JSValue::encode(jsNumber(thisObject->byteOffset()));
377 }
378
379 template<typename ViewClass>
380 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncReverse(VM& vm, ExecState* exec)
381 {
382 //    VM& vm = exec->vm();
383     auto scope = DECLARE_THROW_SCOPE(vm);
384
385     // 22.2.3.21
386     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
387     if (thisObject->isNeutered())
388         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
389
390     typename ViewClass::ElementType* array = thisObject->typedVector();
391     std::reverse(array, array + thisObject->length());
392
393     return JSValue::encode(thisObject);
394 }
395
396 template<typename ViewClass>
397 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewPrivateFuncSort(VM& vm, ExecState* exec)
398 {
399 //    VM& vm = exec->vm();
400     auto scope = DECLARE_THROW_SCOPE(vm);
401
402     // 22.2.3.25
403     ViewClass* thisObject = jsCast<ViewClass*>(exec->argument(0));
404     if (thisObject->isNeutered())
405         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
406
407     thisObject->sort();
408
409     return JSValue::encode(thisObject);
410 }
411
412 template<typename ViewClass>
413 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncSlice(VM& vm, ExecState* exec)
414 {
415     auto scope = DECLARE_THROW_SCOPE(vm);
416
417     // 22.2.3.26
418     JSFunction* callee = jsCast<JSFunction*>(exec->callee());
419
420     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
421     if (thisObject->isNeutered())
422         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
423
424     unsigned thisLength = thisObject->length();
425
426     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, thisLength);
427     RETURN_IF_EXCEPTION(scope, encodedJSValue());
428     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, thisLength, thisLength);
429     RETURN_IF_EXCEPTION(scope, encodedJSValue());
430
431     if (thisObject->isNeutered())
432         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
433
434     // Clamp end to begin.
435     end = std::max(begin, end);
436
437     ASSERT(end >= begin);
438     unsigned length = end - begin;
439
440     MarkedArgumentBuffer args;
441     args.append(jsNumber(length));
442
443     JSArrayBufferView* result = speciesConstruct(exec, thisObject, args, [&]() {
444         Structure* structure = callee->globalObject()->typedArrayStructure(ViewClass::TypedArrayStorageType);
445         return ViewClass::createUninitialized(exec, structure, length);
446     });
447     RETURN_IF_EXCEPTION(scope, encodedJSValue());
448
449     ASSERT(!result->isNeutered());
450     if (thisObject->isNeutered())
451         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
452
453     // We return early here since we don't allocate a backing store if length is 0 and memmove does not like nullptrs
454     if (!length)
455         return JSValue::encode(result);
456
457     // The species constructor may return an array with any arbitrary length.
458     length = std::min(length, result->length());
459     switch (result->classInfo()->typedArrayStorageType) {
460     case TypeInt8:
461         jsCast<JSInt8Array*>(result)->set(exec, 0, thisObject, begin, length, CopyType::LeftToRight);
462         break;
463     case TypeInt16:
464         jsCast<JSInt16Array*>(result)->set(exec, 0, thisObject, begin, length, CopyType::LeftToRight);
465         break;
466     case TypeInt32:
467         jsCast<JSInt32Array*>(result)->set(exec, 0, thisObject, begin, length, CopyType::LeftToRight);
468         break;
469     case TypeUint8:
470         jsCast<JSUint8Array*>(result)->set(exec, 0, thisObject, begin, length, CopyType::LeftToRight);
471         break;
472     case TypeUint8Clamped:
473         jsCast<JSUint8ClampedArray*>(result)->set(exec, 0, thisObject, begin, length, CopyType::LeftToRight);
474         break;
475     case TypeUint16:
476         jsCast<JSUint16Array*>(result)->set(exec, 0, thisObject, begin, length, CopyType::LeftToRight);
477         break;
478     case TypeUint32:
479         jsCast<JSUint32Array*>(result)->set(exec, 0, thisObject, begin, length, CopyType::LeftToRight);
480         break;
481     case TypeFloat32:
482         jsCast<JSFloat32Array*>(result)->set(exec, 0, thisObject, begin, length, CopyType::LeftToRight);
483         break;
484     case TypeFloat64:
485         jsCast<JSFloat64Array*>(result)->set(exec, 0, thisObject, begin, length, CopyType::LeftToRight);
486         break;
487     default:
488         RELEASE_ASSERT_NOT_REACHED();
489     }
490
491     return JSValue::encode(result);
492 }
493
494 template<typename ViewClass>
495 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewPrivateFuncSubarrayCreate(VM&vm, ExecState* exec)
496 {
497     auto scope = DECLARE_THROW_SCOPE(vm);
498
499     // 22.2.3.23
500     JSFunction* callee = jsCast<JSFunction*>(exec->callee());
501
502     ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
503     if (thisObject->isNeutered())
504         return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
505
506     // Get the length here; later assert that the length didn't change.
507     unsigned thisLength = thisObject->length();
508
509     // I would assert that the arguments are integers here but that's not true since
510     // https://tc39.github.io/ecma262/#sec-tointeger allows the result of the operation
511     // to be +/- Infinity and -0.
512     ASSERT(exec->argument(0).isNumber());
513     ASSERT(exec->argument(1).isUndefined() || exec->argument(1).isNumber());
514     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, thisLength);
515     ASSERT(!scope.exception());
516     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, thisLength, thisLength);
517     ASSERT(!scope.exception());
518
519     RELEASE_ASSERT(!thisObject->isNeutered());
520
521     // Clamp end to begin.
522     end = std::max(begin, end);
523
524     ASSERT(end >= begin);
525     unsigned offset = begin;
526     unsigned length = end - begin;
527
528     RefPtr<ArrayBuffer> arrayBuffer = thisObject->buffer();
529     RELEASE_ASSERT(thisLength == thisObject->length());
530
531     unsigned newByteOffset = thisObject->byteOffset() + offset * ViewClass::elementSize;
532
533     JSObject* defaultConstructor = callee->globalObject()->typedArrayConstructor(ViewClass::TypedArrayStorageType);
534     JSValue species = exec->uncheckedArgument(2);
535     if (species == defaultConstructor) {
536         Structure* structure = callee->globalObject()->typedArrayStructure(ViewClass::TypedArrayStorageType);
537
538         return JSValue::encode(ViewClass::create(
539             exec, structure, arrayBuffer,
540             thisObject->byteOffset() + offset * ViewClass::elementSize,
541             length));
542     }
543
544     MarkedArgumentBuffer args;
545     args.append(vm.m_typedArrayController->toJS(exec, thisObject->globalObject(), thisObject->buffer()));
546     args.append(jsNumber(newByteOffset));
547     args.append(jsNumber(length));
548
549     JSObject* result = construct(exec, species, args, "species is not a constructor");
550     RETURN_IF_EXCEPTION(scope, encodedJSValue());
551
552     if (jsDynamicCast<JSArrayBufferView*>(result))
553         return JSValue::encode(result);
554
555     throwTypeError(exec, scope, "species constructor did not return a TypedArray View");
556     return JSValue::encode(JSValue());
557 }
558
559 } // namespace JSC