]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 A |
1 | /* |
2 | * Copyright (C) 2012 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 JSCTypedArrayStubs_h | |
27 | #define JSCTypedArrayStubs_h | |
28 | ||
93a37866 | 29 | #include "JSDestructibleObject.h" |
6fe7ccc8 | 30 | #include "ObjectPrototype.h" |
93a37866 | 31 | #include "Operations.h" |
6fe7ccc8 A |
32 | #include <wtf/Float32Array.h> |
33 | #include <wtf/Float64Array.h> | |
34 | #include <wtf/Forward.h> | |
35 | #include <wtf/Int16Array.h> | |
36 | #include <wtf/Int32Array.h> | |
37 | #include <wtf/Int8Array.h> | |
38 | #include <wtf/Uint16Array.h> | |
39 | #include <wtf/Uint32Array.h> | |
40 | #include <wtf/Uint8Array.h> | |
41 | #include <wtf/Uint8ClampedArray.h> | |
42 | ||
43 | namespace JSC { | |
44 | ||
45 | #define TYPED_ARRAY(name, type) \ | |
93a37866 | 46 | class JS##name##Array : public JSDestructibleObject { \ |
6fe7ccc8 | 47 | public: \ |
93a37866 | 48 | typedef JSDestructibleObject Base; \ |
6fe7ccc8 A |
49 | static JS##name##Array* create(JSC::Structure* structure, JSGlobalObject* globalObject, PassRefPtr<name##Array> impl) \ |
50 | { \ | |
93a37866 A |
51 | JS##name##Array* ptr = new (NotNull, JSC::allocateCell<JS##name##Array>(globalObject->vm().heap)) JS##name##Array(structure, globalObject, impl); \ |
52 | ptr->finishCreation(globalObject->vm()); \ | |
6fe7ccc8 A |
53 | return ptr; \ |
54 | }\ | |
55 | \ | |
93a37866 A |
56 | static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName propertyName, JSC::PropertySlot&);\ |
57 | static bool getOwnPropertyDescriptor(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName propertyName, JSC::PropertyDescriptor&);\ | |
6fe7ccc8 | 58 | static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\ |
93a37866 | 59 | static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName propertyName, JSC::JSValue, JSC::PutPropertySlot&);\ |
6fe7ccc8 A |
60 | static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool);\ |
61 | static const JSC::ClassInfo s_info;\ | |
62 | \ | |
93a37866 | 63 | static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\ |
6fe7ccc8 | 64 | {\ |
93a37866 | 65 | return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), &s_info);\ |
6fe7ccc8 A |
66 | }\ |
67 | \ | |
68 | static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\ | |
69 | static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\ | |
70 | \ | |
71 | static const JSC::TypedArrayType TypedArrayStorageType = JSC::TypedArray##name;\ | |
72 | uint32_t m_storageLength;\ | |
73 | type* m_storage;\ | |
74 | RefPtr<name##Array> m_impl;\ | |
75 | protected:\ | |
76 | JS##name##Array(JSC::Structure*, JSGlobalObject*, PassRefPtr<name##Array>);\ | |
93a37866 A |
77 | void finishCreation(JSC::VM&);\ |
78 | static const unsigned StructureFlags = JSC::OverridesGetPropertyNames | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | Base::StructureFlags; \ | |
6fe7ccc8 A |
79 | JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\ |
80 | void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\ | |
81 | };\ | |
82 | \ | |
83 | const ClassInfo JS##name##Array::s_info = { #name "Array" , &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JS##name##Array) };\ | |
84 | \ | |
85 | JS##name##Array::JS##name##Array(Structure* structure, JSGlobalObject* globalObject, PassRefPtr<name##Array> impl)\ | |
93a37866 | 86 | : Base(globalObject->vm(), structure)\ |
6fe7ccc8 A |
87 | , m_impl(impl)\ |
88 | {\ | |
89 | }\ | |
90 | \ | |
93a37866 | 91 | void JS##name##Array::finishCreation(VM& vm)\ |
6fe7ccc8 | 92 | {\ |
93a37866 | 93 | Base::finishCreation(vm);\ |
6fe7ccc8 | 94 | TypedArrayDescriptor descriptor(&JS##name##Array::s_info, OBJECT_OFFSETOF(JS##name##Array, m_storage), OBJECT_OFFSETOF(JS##name##Array, m_storageLength));\ |
93a37866 | 95 | vm.registerTypedArrayDescriptor(m_impl.get(), descriptor);\ |
6fe7ccc8 A |
96 | m_storage = m_impl->data();\ |
97 | m_storageLength = m_impl->length();\ | |
93a37866 | 98 | putDirect(vm, vm.propertyNames->length, jsNumber(m_storageLength), DontDelete | ReadOnly | DontEnum); \ |
6fe7ccc8 A |
99 | ASSERT(inherits(&s_info));\ |
100 | }\ | |
101 | \ | |
93a37866 | 102 | bool JS##name##Array::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)\ |
6fe7ccc8 A |
103 | {\ |
104 | JS##name##Array* thisObject = jsCast<JS##name##Array*>(cell);\ | |
105 | ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\ | |
93a37866 A |
106 | unsigned index = propertyName.asIndex();\ |
107 | if (index < thisObject->m_storageLength) {\ | |
108 | ASSERT(index != PropertyName::NotAnIndex);\ | |
6fe7ccc8 A |
109 | slot.setValue(thisObject->getByIndex(exec, index));\ |
110 | return true;\ | |
111 | }\ | |
112 | return Base::getOwnPropertySlot(cell, exec, propertyName, slot);\ | |
113 | }\ | |
114 | \ | |
93a37866 | 115 | bool JS##name##Array::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)\ |
6fe7ccc8 A |
116 | {\ |
117 | JS##name##Array* thisObject = jsCast<JS##name##Array*>(object);\ | |
118 | ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\ | |
93a37866 A |
119 | unsigned index = propertyName.asIndex();\ |
120 | if (index < thisObject->m_storageLength) {\ | |
121 | ASSERT(index != PropertyName::NotAnIndex);\ | |
6fe7ccc8 A |
122 | descriptor.setDescriptor(thisObject->getByIndex(exec, index), DontDelete);\ |
123 | return true;\ | |
124 | }\ | |
125 | return Base::getOwnPropertyDescriptor(object, exec, propertyName, descriptor);\ | |
126 | }\ | |
127 | \ | |
128 | bool JS##name##Array::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)\ | |
129 | {\ | |
130 | JS##name##Array* thisObject = jsCast<JS##name##Array*>(cell);\ | |
131 | ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\ | |
132 | if (propertyName < thisObject->m_storageLength) {\ | |
133 | slot.setValue(thisObject->getByIndex(exec, propertyName));\ | |
134 | return true;\ | |
135 | }\ | |
136 | return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot);\ | |
137 | }\ | |
138 | \ | |
93a37866 | 139 | void JS##name##Array::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)\ |
6fe7ccc8 A |
140 | {\ |
141 | JS##name##Array* thisObject = jsCast<JS##name##Array*>(cell);\ | |
142 | ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\ | |
93a37866 A |
143 | unsigned index = propertyName.asIndex();\ |
144 | if (index != PropertyName::NotAnIndex) {\ | |
6fe7ccc8 A |
145 | thisObject->indexSetter(exec, index, value);\ |
146 | return;\ | |
147 | }\ | |
148 | Base::put(thisObject, exec, propertyName, value, slot);\ | |
149 | }\ | |
150 | \ | |
151 | void JS##name##Array::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value) \ | |
152 | {\ | |
153 | m_impl->set(index, value.toNumber(exec));\ | |
154 | }\ | |
155 | \ | |
156 | void JS##name##Array::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool)\ | |
157 | {\ | |
158 | JS##name##Array* thisObject = jsCast<JS##name##Array*>(cell);\ | |
159 | ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\ | |
160 | thisObject->indexSetter(exec, propertyName, value);\ | |
161 | return;\ | |
162 | }\ | |
163 | \ | |
164 | void JS##name##Array::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\ | |
165 | {\ | |
166 | JS##name##Array* thisObject = jsCast<JS##name##Array*>(object);\ | |
167 | ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\ | |
168 | for (unsigned i = 0; i < thisObject->m_storageLength; ++i)\ | |
169 | propertyNames.add(Identifier::from(exec, i));\ | |
170 | Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);\ | |
171 | }\ | |
172 | \ | |
173 | JSValue JS##name##Array::getByIndex(ExecState*, unsigned index)\ | |
174 | {\ | |
175 | ASSERT_GC_OBJECT_INHERITS(this, &s_info);\ | |
176 | type result = m_impl->item(index);\ | |
93a37866 | 177 | if (std::isnan((double)result))\ |
6fe7ccc8 A |
178 | return jsNaN();\ |
179 | return JSValue(result);\ | |
180 | }\ | |
181 | static EncodedJSValue JSC_HOST_CALL constructJS##name##Array(ExecState* callFrame) { \ | |
182 | if (callFrame->argumentCount() < 1) \ | |
183 | return JSValue::encode(jsUndefined()); \ | |
184 | int32_t length = callFrame->argument(0).toInt32(callFrame); \ | |
185 | if (length < 0) \ | |
186 | return JSValue::encode(jsUndefined()); \ | |
93a37866 A |
187 | Structure* structure = JS##name##Array::createStructure(callFrame->vm(), callFrame->lexicalGlobalObject(), callFrame->lexicalGlobalObject()->objectPrototype()); \ |
188 | RefPtr<name##Array> buffer = name##Array::create(length); \ | |
189 | if (!buffer) \ | |
190 | return throwVMError(callFrame, createRangeError(callFrame, "ArrayBuffer size is not a small enough positive integer.")); \ | |
191 | return JSValue::encode(JS##name##Array::create(structure, callFrame->lexicalGlobalObject(), buffer.release())); \ | |
6fe7ccc8 A |
192 | } |
193 | ||
194 | TYPED_ARRAY(Uint8, uint8_t); | |
195 | TYPED_ARRAY(Uint8Clamped, uint8_t); | |
196 | TYPED_ARRAY(Uint16, uint16_t); | |
197 | TYPED_ARRAY(Uint32, uint32_t); | |
198 | TYPED_ARRAY(Int8, int8_t); | |
199 | TYPED_ARRAY(Int16, int16_t); | |
200 | TYPED_ARRAY(Int32, int32_t); | |
201 | TYPED_ARRAY(Float32, float); | |
202 | TYPED_ARRAY(Float64, double); | |
203 | ||
204 | } | |
205 | ||
206 | #endif |