Rewrite Function.bind as a builtin
[WebKit.git] / Source / JavaScriptCore / runtime / JSGenericTypedArrayViewConstructorInlines.h
1 /*
2  * Copyright (C) 2013 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 #ifndef JSGenericTypedArrayViewConstructorInlines_h
27 #define JSGenericTypedArrayViewConstructorInlines_h
28
29 #include "Error.h"
30 #include "JSArrayBuffer.h"
31 #include "JSGenericTypedArrayViewConstructor.h"
32 #include "JSGlobalObject.h"
33
34 namespace JSC {
35
36 template<typename ViewClass>
37 JSGenericTypedArrayViewConstructor<ViewClass>::JSGenericTypedArrayViewConstructor(VM& vm, Structure* structure)
38     : Base(vm, structure)
39 {
40 }
41
42 template<typename ViewClass>
43 void JSGenericTypedArrayViewConstructor<ViewClass>::finishCreation(VM& vm, JSObject* prototype, const String& name)
44 {
45     Base::finishCreation(vm, name);
46     putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
47     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(3), DontEnum | DontDelete | ReadOnly);
48     putDirectWithoutTransition(vm, vm.propertyNames->BYTES_PER_ELEMENT, jsNumber(ViewClass::elementSize), DontEnum | ReadOnly | DontDelete);
49 }
50
51 template<typename ViewClass>
52 JSGenericTypedArrayViewConstructor<ViewClass>*
53 JSGenericTypedArrayViewConstructor<ViewClass>::create(
54     VM& vm, Structure* structure, JSObject* prototype,
55     const String& name)
56 {
57     JSGenericTypedArrayViewConstructor* result =
58         new (NotNull, allocateCell<JSGenericTypedArrayViewConstructor>(vm.heap))
59         JSGenericTypedArrayViewConstructor(vm, structure);
60     result->finishCreation(vm, prototype, name);
61     return result;
62 }
63
64 template<typename ViewClass>
65 Structure* JSGenericTypedArrayViewConstructor<ViewClass>::createStructure(
66     VM& vm, JSGlobalObject* globalObject, JSValue prototype)
67 {
68     return Structure::create(
69         vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
70 }
71
72 template<typename ViewClass>
73 static EncodedJSValue JSC_HOST_CALL constructGenericTypedArrayView(ExecState* exec)
74 {
75     Structure* structure =
76         asInternalFunction(exec->callee())->globalObject()->typedArrayStructure(
77             ViewClass::TypedArrayStorageType);
78     
79     if (!exec->argumentCount()) {
80         if (ViewClass::TypedArrayStorageType == TypeDataView)
81             return throwVMError(exec, createTypeError(exec, "DataView constructor requires at least one argument."));
82         
83         // Even though the documentation doesn't say so, it's correct to say
84         // "new Int8Array()". This is the same as allocating an array of zero
85         // length.
86         return JSValue::encode(ViewClass::create(exec, structure, 0));
87     }
88     
89     if (JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0))) {
90         RefPtr<ArrayBuffer> buffer = jsBuffer->impl();
91         
92         unsigned offset = (exec->argumentCount() > 1) ? exec->uncheckedArgument(1).toUInt32(exec) : 0;
93         if (exec->hadException())
94             return JSValue::encode(jsUndefined());
95         unsigned length = 0;
96         if (exec->argumentCount() > 2) {
97             length = exec->uncheckedArgument(2).toUInt32(exec);
98             if (exec->hadException())
99                 return JSValue::encode(jsUndefined());
100         } else {
101             if ((buffer->byteLength() - offset) % ViewClass::elementSize)
102                 return throwVMError(exec, createRangeError(exec, "ArrayBuffer length minus the byteOffset is not a multiple of the element size"));
103             length = (buffer->byteLength() - offset) / ViewClass::elementSize;
104         }
105         return JSValue::encode(ViewClass::create(exec, structure, buffer, offset, length));
106     }
107     
108     if (ViewClass::TypedArrayStorageType == TypeDataView)
109         return throwVMError(exec, createTypeError(exec, "Expected ArrayBuffer for the first argument."));
110     
111     // For everything but DataView, we allow construction with any of:
112     // - Another array. This creates a copy of the of that array.
113     // - An integer. This creates a new typed array of that length and zero-initializes it.
114     
115     if (JSObject* object = jsDynamicCast<JSObject*>(exec->uncheckedArgument(0))) {
116         unsigned length =
117             object->get(exec, exec->vm().propertyNames->length).toUInt32(exec);
118         if (exec->hadException())
119             return JSValue::encode(jsUndefined());
120         
121         ViewClass* result = ViewClass::createUninitialized(exec, structure, length);
122         if (!result) {
123             ASSERT(exec->hadException());
124             return JSValue::encode(jsUndefined());
125         }
126         
127         if (!result->set(exec, object, 0, length))
128             return JSValue::encode(jsUndefined());
129         
130         return JSValue::encode(result);
131     }
132     
133     int length;
134     if (exec->uncheckedArgument(0).isInt32())
135         length = exec->uncheckedArgument(0).asInt32();
136     else if (!exec->uncheckedArgument(0).isNumber())
137         return throwVMError(exec, createTypeError(exec, "Invalid array length argument"));
138     else {
139         length = static_cast<int>(exec->uncheckedArgument(0).asNumber());
140         if (length != exec->uncheckedArgument(0).asNumber())
141             return throwVMError(exec, createTypeError(exec, "Invalid array length argument (fractional lengths not allowed)"));
142     }
143
144     if (length < 0)
145         return throwVMError(exec, createRangeError(exec, "Requested length is negative"));
146     return JSValue::encode(ViewClass::create(exec, structure, length));
147 }
148
149 template<typename ViewClass>
150 ConstructType JSGenericTypedArrayViewConstructor<ViewClass>::getConstructData(JSCell*, ConstructData& constructData)
151 {
152     constructData.native.function = constructGenericTypedArrayView<ViewClass>;
153     return ConstructTypeHost;
154 }
155
156 template<typename ViewClass>
157 CallType JSGenericTypedArrayViewConstructor<ViewClass>::getCallData(JSCell*, CallData& callData)
158 {
159     callData.native.function = constructGenericTypedArrayView<ViewClass>;
160     return CallTypeNone;
161 }
162
163 } // namespace JSC
164
165 #endif // JSGenericTypedArrayViewConstructorInlines_h