We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSTypedArrayViewPrototype.cpp
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 #include "config.h"
27 #include "JSTypedArrayViewPrototype.h"
28
29 #include "BuiltinNames.h"
30 #include "CallFrame.h"
31 #include "GetterSetter.h"
32 #include "JSCInlines.h"
33 #include "JSFunction.h"
34 #include "JSGenericTypedArrayViewPrototypeFunctions.h"
35 #include "JSObjectInlines.h"
36 #include "TypedArrayAdaptors.h"
37
38 namespace JSC {
39
40 #define CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(functionName) do {                           \
41     switch (thisValue.getObject()->classInfo(vm)->typedArrayStorageType) {                        \
42     case TypeUint8Clamped:                                                                      \
43         return functionName<JSUint8ClampedArray>(vm, exec);                                     \
44     case TypeInt32:                                                                             \
45         return functionName<JSInt32Array>(vm, exec);                                            \
46     case TypeUint32:                                                                            \
47         return functionName<JSUint32Array>(vm, exec);                                           \
48     case TypeFloat64:                                                                           \
49         return functionName<JSFloat64Array>(vm, exec);                                          \
50     case TypeFloat32:                                                                           \
51         return functionName<JSFloat32Array>(vm, exec);                                          \
52     case TypeInt8:                                                                              \
53         return functionName<JSInt8Array>(vm, exec);                                             \
54     case TypeUint8:                                                                             \
55         return functionName<JSUint8Array>(vm, exec);                                            \
56     case TypeInt16:                                                                             \
57         return functionName<JSInt16Array>(vm, exec);                                            \
58     case TypeUint16:                                                                            \
59         return functionName<JSUint16Array>(vm, exec);                                           \
60     case NotTypedArray:                                                                         \
61     case TypeDataView:                                                                          \
62         return throwVMTypeError(exec, scope,                                                    \
63             "Receiver should be a typed array view"_s);                             \
64     }                                                                                           \
65     RELEASE_ASSERT_NOT_REACHED();                                                               \
66 } while (false)
67
68 EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncIsTypedArrayView(ExecState* exec)
69 {
70     JSValue value = exec->uncheckedArgument(0);
71     return JSValue::encode(jsBoolean(value.isCell() && isTypedView(value.asCell()->classInfo(exec->vm())->typedArrayStorageType)));
72 }
73
74 EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncLength(ExecState* exec)
75 {
76     VM& vm = exec->vm();
77     auto scope = DECLARE_THROW_SCOPE(vm);
78     JSValue argument = exec->argument(0);
79     if (!argument.isCell() || !isTypedView(argument.asCell()->classInfo(vm)->typedArrayStorageType))
80         return throwVMTypeError(exec, scope, "Receiver should be a typed array view"_s);
81
82     JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(argument);
83
84     if (thisObject->isNeutered())
85         return throwVMTypeError(exec, scope, "Underlying ArrayBuffer has been detached from the view"_s);
86
87     return JSValue::encode(jsNumber(thisObject->length()));
88 }
89
90 EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncGetOriginalConstructor(ExecState* exec)
91 {
92     VM& vm = exec->vm();
93     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
94     TypedArrayType type = exec->uncheckedArgument(0).getObject()->classInfo(vm)->typedArrayStorageType;
95     ASSERT(isTypedView(type));
96     return JSValue::encode(globalObject->typedArrayConstructor(type));
97 }
98
99 EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncSort(ExecState* exec)
100 {
101     VM& vm = exec->vm();
102     auto scope = DECLARE_THROW_SCOPE(vm);
103     JSValue thisValue = exec->argument(0);
104     scope.release();
105     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewPrivateFuncSort);
106 }
107
108 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncSet(ExecState* exec)
109 {
110     VM& vm = exec->vm();
111     auto scope = DECLARE_THROW_SCOPE(vm);
112     JSValue thisValue = exec->thisValue();
113     if (UNLIKELY(!thisValue.isObject()))
114         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
115     scope.release();
116     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoFuncSet);
117 }
118
119 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncCopyWithin(ExecState* exec)
120 {
121     VM& vm = exec->vm();
122     auto scope = DECLARE_THROW_SCOPE(vm);
123     JSValue thisValue = exec->thisValue();
124     if (!thisValue.isObject())
125         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
126     scope.release();
127     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoFuncCopyWithin);
128 }
129
130 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncIncludes(ExecState* exec)
131 {
132     VM& vm = exec->vm();
133     auto scope = DECLARE_THROW_SCOPE(vm);
134     JSValue thisValue = exec->thisValue();
135     if (!thisValue.isObject())
136         return throwVMError(exec, scope, createTypeError(exec, "Receiver should be a typed array view but was not an object"));
137     scope.release();
138     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoFuncIncludes);
139 }
140
141 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncLastIndexOf(ExecState* exec)
142 {
143     VM& vm = exec->vm();
144     auto scope = DECLARE_THROW_SCOPE(vm);
145     JSValue thisValue = exec->thisValue();
146     if (!thisValue.isObject())
147         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
148     scope.release();
149     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoFuncLastIndexOf);
150 }
151
152 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncIndexOf(ExecState* exec)
153 {
154     VM& vm = exec->vm();
155     auto scope = DECLARE_THROW_SCOPE(vm);
156     JSValue thisValue = exec->thisValue();
157     if (!thisValue.isObject())
158         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
159     scope.release();
160     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoFuncIndexOf);
161 }
162
163 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncJoin(ExecState* exec)
164 {
165     VM& vm = exec->vm();
166     auto scope = DECLARE_THROW_SCOPE(vm);
167     JSValue thisValue = exec->thisValue();
168     if (!thisValue.isObject())
169         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
170     scope.release();
171     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoFuncJoin);
172 }
173
174 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoGetterFuncBuffer(ExecState* exec)
175 {
176     VM& vm = exec->vm();
177     auto scope = DECLARE_THROW_SCOPE(vm);
178     JSValue thisValue = exec->thisValue();
179     if (!thisValue.isObject())
180         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
181     scope.release();
182     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoGetterFuncBuffer);
183 }
184
185 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoGetterFuncLength(ExecState* exec)
186 {
187     VM& vm = exec->vm();
188     auto scope = DECLARE_THROW_SCOPE(vm);
189     JSValue thisValue = exec->thisValue();
190     if (!thisValue.isObject())
191         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
192     scope.release();
193     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoGetterFuncLength);
194 }
195
196 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoGetterFuncByteLength(ExecState* exec)
197 {
198     VM& vm = exec->vm();
199     auto scope = DECLARE_THROW_SCOPE(vm);
200     JSValue thisValue = exec->thisValue();
201     if (!thisValue.isObject())
202         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
203     scope.release();
204     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoGetterFuncByteLength);
205 }
206
207 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoGetterFuncByteOffset(ExecState* exec)
208 {
209     VM& vm = exec->vm();
210     auto scope = DECLARE_THROW_SCOPE(vm);
211     JSValue thisValue = exec->thisValue();
212     if (!thisValue.isObject())
213         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
214     scope.release();
215     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoGetterFuncByteOffset);
216 }
217
218 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncReverse(ExecState* exec)
219 {
220     VM& vm = exec->vm();
221     auto scope = DECLARE_THROW_SCOPE(vm);
222     JSValue thisValue = exec->thisValue();
223     if (!thisValue.isObject())
224         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
225     scope.release();
226     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoFuncReverse);
227 }
228
229 EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncSubarrayCreate(ExecState* exec)
230 {
231     VM& vm = exec->vm();
232     auto scope = DECLARE_THROW_SCOPE(vm);
233     JSValue thisValue = exec->thisValue();
234     if (!thisValue.isObject())
235         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
236     scope.release();
237     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewPrivateFuncSubarrayCreate);
238 }
239
240 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncSlice(ExecState* exec)
241 {
242     VM& vm = exec->vm();
243     auto scope = DECLARE_THROW_SCOPE(vm);
244     JSValue thisValue = exec->thisValue();
245     if (!thisValue.isObject())
246         return throwVMTypeError(exec, scope, "Receiver should be a typed array view but was not an object"_s);
247     scope.release();
248     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoFuncSlice);
249 }
250
251 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoGetterFuncToStringTag(ExecState* exec)
252 {
253     JSValue thisValue = exec->thisValue();
254     if (!thisValue.isObject())
255         return JSValue::encode(jsUndefined());
256
257     VM& vm = exec->vm();
258     switch (thisValue.getObject()->classInfo(vm)->typedArrayStorageType) {
259     case TypeUint8Clamped:
260         return JSValue::encode(jsString(&vm, "Uint8ClampedArray"));
261     case TypeInt32:
262         return JSValue::encode(jsString(&vm, "Int32Array"));
263     case TypeUint32:
264         return JSValue::encode(jsString(&vm, "Uint32Array"));
265     case TypeFloat64:
266         return JSValue::encode(jsString(&vm, "Float64Array"));
267     case TypeFloat32:
268         return JSValue::encode(jsString(&vm, "Float32Array"));
269     case TypeInt8:
270         return JSValue::encode(jsString(&vm, "Int8Array"));
271     case TypeUint8:
272         return JSValue::encode(jsString(&vm, "Uint8Array"));
273     case TypeInt16:
274         return JSValue::encode(jsString(&vm, "Int16Array"));
275     case TypeUint16:
276         return JSValue::encode(jsString(&vm, "Uint16Array"));
277     case NotTypedArray:
278     case TypeDataView:
279         return JSValue::encode(jsUndefined());
280     }
281     RELEASE_ASSERT_NOT_REACHED();
282 }
283
284
285 #undef CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION
286
287 JSTypedArrayViewPrototype::JSTypedArrayViewPrototype(VM& vm, Structure* structure)
288     : Base(vm, structure)
289 {
290 }
291
292 void JSTypedArrayViewPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
293 {
294     Base::finishCreation(vm);
295
296     ASSERT(inherits(vm, info()));
297
298     putDirectWithoutTransition(vm, vm.propertyNames->toString, globalObject->arrayProtoToStringFunction(), static_cast<unsigned>(PropertyAttribute::DontEnum));
299
300     JSC_NATIVE_GETTER(vm.propertyNames->buffer, typedArrayViewProtoGetterFuncBuffer, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
301     JSC_NATIVE_INTRINSIC_GETTER(vm.propertyNames->byteLength, typedArrayViewProtoGetterFuncByteLength, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly, TypedArrayByteLengthIntrinsic);
302     JSC_NATIVE_INTRINSIC_GETTER(vm.propertyNames->byteOffset, typedArrayViewProtoGetterFuncByteOffset, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly, TypedArrayByteOffsetIntrinsic);
303     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("copyWithin", typedArrayViewProtoFuncCopyWithin, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
304     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("every", typedArrayPrototypeEveryCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
305     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("filter", typedArrayPrototypeFilterCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
306     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("sort", typedArrayPrototypeSortCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
307     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), typedArrayPrototypeEntriesCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
308     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("includes", typedArrayViewProtoFuncIncludes, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
309     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("fill", typedArrayPrototypeFillCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
310     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("find", typedArrayPrototypeFindCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
311     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("findIndex", typedArrayPrototypeFindIndexCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
312     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->forEach, typedArrayPrototypeForEachCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
313     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("indexOf", typedArrayViewProtoFuncIndexOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
314     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->join, typedArrayViewProtoFuncJoin, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
315     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().keysPublicName(), typedArrayPrototypeKeysCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
316     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("lastIndexOf", typedArrayViewProtoFuncLastIndexOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
317     JSC_NATIVE_INTRINSIC_GETTER(vm.propertyNames->length, typedArrayViewProtoGetterFuncLength, static_cast<unsigned>(PropertyAttribute::DontEnum) | PropertyAttribute::ReadOnly, TypedArrayLengthIntrinsic);
318     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("map", typedArrayPrototypeMapCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
319     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("reduce", typedArrayPrototypeReduceCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
320     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("reduceRight", typedArrayPrototypeReduceRightCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
321     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("reverse", typedArrayViewProtoFuncReverse, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
322     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->set, typedArrayViewProtoFuncSet, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
323     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->slice, typedArrayViewProtoFuncSlice, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
324     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("some", typedArrayPrototypeSomeCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
325     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->subarray, typedArrayPrototypeSubarrayCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
326     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toLocaleString, typedArrayPrototypeToLocaleStringCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
327
328     JSFunction* toStringTagFunction = JSFunction::create(vm, globalObject, 0, "get [Symbol.toStringTag]"_s, typedArrayViewProtoGetterFuncToStringTag, NoIntrinsic);
329     GetterSetter* toStringTagAccessor = GetterSetter::create(vm, globalObject, toStringTagFunction, nullptr);
330     putDirectNonIndexAccessor(vm, vm.propertyNames->toStringTagSymbol, toStringTagAccessor, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly | PropertyAttribute::Accessor);
331
332     JSFunction* valuesFunction = JSFunction::create(vm, typedArrayPrototypeValuesCodeGenerator(vm), globalObject);
333
334     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPublicName(), valuesFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
335     putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, valuesFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
336
337 }
338
339 JSTypedArrayViewPrototype* JSTypedArrayViewPrototype::create(
340     VM& vm, JSGlobalObject* globalObject, Structure* structure)
341 {
342     JSTypedArrayViewPrototype* prototype =
343         new (NotNull, allocateCell<JSTypedArrayViewPrototype>(vm.heap))
344         JSTypedArrayViewPrototype(vm, structure);
345     prototype->finishCreation(vm, globalObject);
346     return prototype;
347 }
348
349 Structure* JSTypedArrayViewPrototype::createStructure(
350     VM& vm, JSGlobalObject* globalObject, JSValue prototype)
351 {
352     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
353 }
354
355 } // namespace JSC