1 /* 2 * Copyright (C) 2013 Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef V8TypedArrayCustom_h 32 #define V8TypedArrayCustom_h 33 34 #include "bindings/core/v8/V8Binding.h" 35 #include "bindings/core/v8/V8DOMWrapper.h" 36 #include "bindings/core/v8/WrapperTypeInfo.h" 37 #include "bindings/core/v8/custom/V8ArrayBufferCustom.h" 38 #include "wtf/ArrayBuffer.h" 39 #include <v8.h> 40 41 namespace blink { 42 43 template<typename T> 44 class TypedArrayTraits 45 { }; 46 47 template<typename TypedArray> 48 class V8TypedArray { 49 public: 50 static bool hasInstance(v8::Handle<v8::Value> value, v8::Isolate*) 51 { 52 return TypedArrayTraits<TypedArray>::IsInstance(value); 53 } 54 55 static TypedArray* toImpl(v8::Handle<v8::Object>); 56 static TypedArray* toImplWithTypeCheck(v8::Isolate*, v8::Handle<v8::Value>); 57 static void refObject(ScriptWrappableBase* internalPointer); 58 static void derefObject(ScriptWrappableBase* internalPointer); 59 static WrapperPersistentNode* createPersistentHandle(ScriptWrappableBase* internalPointer); 60 static const WrapperTypeInfo wrapperTypeInfo; 61 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount; 62 63 static v8::Handle<v8::Object> wrap(TypedArray* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 64 { 65 ASSERT(impl); 66 ASSERT(!DOMDataStore::containsWrapper<Binding>(impl, isolate)); 67 return V8TypedArray<TypedArray>::createWrapper(impl, creationContext, isolate); 68 } 69 70 static v8::Handle<v8::Value> toV8(TypedArray* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 71 { 72 if (UNLIKELY(!impl)) 73 return v8::Null(isolate); 74 v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper<Binding>(impl, isolate); 75 if (!wrapper.IsEmpty()) 76 return wrapper; 77 return wrap(impl, creationContext, isolate); 78 } 79 80 template<typename CallbackInfo> 81 static void v8SetReturnValue(const CallbackInfo& info, TypedArray* impl) 82 { 83 if (UNLIKELY(!impl)) { 84 v8SetReturnValueNull(info); 85 return; 86 } 87 if (DOMDataStore::setReturnValueFromWrapper<Binding>(info.GetReturnValue(), impl)) 88 return; 89 v8::Handle<v8::Object> wrapper = wrap(impl, info.Holder(), info.GetIsolate()); 90 info.GetReturnValue().Set(wrapper); 91 } 92 93 template<typename CallbackInfo> 94 static void v8SetReturnValueForMainWorld(const CallbackInfo& info, TypedArray* impl) 95 { 96 ASSERT(DOMWrapperWorld::current(info.GetIsolate()).isMainWorld()); 97 if (UNLIKELY(!impl)) { 98 v8SetReturnValueNull(info); 99 return; 100 } 101 if (DOMDataStore::setReturnValueFromWrapperForMainWorld<Binding>(info.GetReturnValue(), impl)) 102 return; 103 v8::Handle<v8::Value> wrapper = wrap(impl, info.Holder(), info.GetIsolate()); 104 info.GetReturnValue().Set(wrapper); 105 } 106 107 template<class CallbackInfo, class Wrappable> 108 static void v8SetReturnValueFast(const CallbackInfo& info, TypedArray* impl, Wrappable* wrappable) 109 { 110 if (UNLIKELY(!impl)) { 111 v8SetReturnValueNull(info); 112 return; 113 } 114 if (DOMDataStore::setReturnValueFromWrapperFast<Binding>(info.GetReturnValue(), impl, info.Holder(), wrappable)) 115 return; 116 v8::Handle<v8::Object> wrapper = wrap(impl, info.Holder(), info.GetIsolate()); 117 info.GetReturnValue().Set(wrapper); 118 } 119 120 static inline ScriptWrappableBase* toScriptWrappableBase(TypedArray* impl) 121 { 122 return reinterpret_cast<ScriptWrappableBase*>(static_cast<void*>(impl)); 123 } 124 125 static inline TypedArray* toImpl(ScriptWrappableBase* internalPointer) 126 { 127 return reinterpret_cast<TypedArray*>(static_cast<void*>(internalPointer)); 128 } 129 private: 130 typedef TypedArrayTraits<TypedArray> Traits; 131 typedef typename Traits::V8Type V8Type; 132 typedef V8TypedArray<TypedArray> Binding; 133 134 static v8::Handle<v8::Object> createWrapper(PassRefPtr<TypedArray>, v8::Handle<v8::Object> creationContext, v8::Isolate*); 135 }; 136 137 template<typename TypedArray> 138 class TypedArrayWrapperTraits { 139 public: 140 static const WrapperTypeInfo* info() { return &V8TypedArray<TypedArray>::wrapperTypeInfo; } 141 }; 142 143 144 template <typename TypedArray> 145 v8::Handle<v8::Object> V8TypedArray<TypedArray>::createWrapper(PassRefPtr<TypedArray> impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 146 { 147 ASSERT(impl.get()); 148 ASSERT(!DOMDataStore::containsWrapper<Binding>(impl.get(), isolate)); 149 150 RefPtr<ArrayBuffer> buffer = impl->buffer(); 151 v8::Local<v8::Value> v8Buffer = blink::toV8(buffer.get(), creationContext, isolate); 152 153 ASSERT(v8Buffer->IsArrayBuffer()); 154 155 v8::Local<v8::Object> wrapper = V8Type::New(v8Buffer.As<v8::ArrayBuffer>(), impl->byteOffset(), Traits::length(impl.get())); 156 157 V8DOMWrapper::associateObjectWithWrapper<Binding>(impl, &wrapperTypeInfo, wrapper, isolate); 158 return wrapper; 159 } 160 161 template <typename TypedArray> 162 TypedArray* V8TypedArray<TypedArray>::toImpl(v8::Handle<v8::Object> object) 163 { 164 ASSERT(Traits::IsInstance(object)); 165 void* typedarrayPtr = object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex); 166 if (typedarrayPtr) 167 return reinterpret_cast<TypedArray*>(typedarrayPtr); 168 169 v8::Handle<V8Type> view = object.As<V8Type>(); 170 RefPtr<ArrayBuffer> arrayBuffer = V8ArrayBuffer::toImpl(view->Buffer()); 171 RefPtr<TypedArray> typedArray = TypedArray::create(arrayBuffer, view->ByteOffset(), Traits::length(view)); 172 ASSERT(typedArray.get()); 173 V8DOMWrapper::associateObjectWithWrapper<Binding>(typedArray.release(), &wrapperTypeInfo, object, v8::Isolate::GetCurrent()); 174 175 typedarrayPtr = object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex); 176 ASSERT(typedarrayPtr); 177 return reinterpret_cast<TypedArray*>(typedarrayPtr); 178 } 179 180 template <typename TypedArray> 181 TypedArray* V8TypedArray<TypedArray>::toImplWithTypeCheck(v8::Isolate* isolate, v8::Handle<v8::Value> value) 182 { 183 return V8TypedArray<TypedArray>::hasInstance(value, isolate) ? V8TypedArray<TypedArray>::toImpl(v8::Handle<v8::Object>::Cast(value)) : 0; 184 } 185 186 template <typename TypedArray> 187 const WrapperTypeInfo V8TypedArray<TypedArray>::wrapperTypeInfo = { 188 gin::kEmbedderBlink, 189 0, 190 V8TypedArray<TypedArray>::refObject, 191 V8TypedArray<TypedArray>::derefObject, 192 V8TypedArray<TypedArray>::createPersistentHandle, 193 0, 0, 0, 0, 0, 0, 194 WrapperTypeInfo::WrapperTypeObjectPrototype, 195 WrapperTypeInfo::ObjectClassId, 196 WrapperTypeInfo::Independent, 197 WrapperTypeInfo::RefCountedObject 198 }; 199 200 template <typename TypedArray> 201 void V8TypedArray<TypedArray>::refObject(ScriptWrappableBase* internalPointer) 202 { 203 toImpl(internalPointer)->ref(); 204 } 205 206 template <typename TypedArray> 207 void V8TypedArray<TypedArray>::derefObject(ScriptWrappableBase* internalPointer) 208 { 209 toImpl(internalPointer)->deref(); 210 } 211 212 template <typename TypedArray> 213 WrapperPersistentNode* V8TypedArray<TypedArray>::createPersistentHandle(ScriptWrappableBase* internalPointer) 214 { 215 ASSERT_NOT_REACHED(); 216 return 0; 217 } 218 219 } // namespace blink 220 221 #endif // V8TypedArrayCustom_h 222