1 /* 2 * Copyright (C) 2009 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 #include "config.h" 32 33 #if ENABLE(3D_CANVAS) 34 35 #include "WebGLArrayBuffer.h" 36 37 #include "V8Binding.h" 38 #include "V8WebGLArrayBuffer.h" 39 #include "V8Proxy.h" 40 41 namespace WebCore { 42 43 // Template function used by the WebGLArray*Constructor callbacks. 44 template<class ArrayClass> 45 v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, 46 int classIndex) 47 { 48 if (!args.IsConstructCall()) 49 return throwError("DOM object constructor cannot be called as a function."); 50 51 int argLen = args.Length(); 52 if (argLen == 0) { 53 // This happens when we return a previously constructed 54 // WebGLArray, e.g. from the call to WebGL<T>Array.slice(). 55 // The V8DOMWrapper will set the internal pointer in the 56 // created object. Unfortunately it doesn't look like it's 57 // possible to distinguish between this case and that where 58 // the user calls "new WebGL<T>Array()" from JavaScript. 59 return args.Holder(); 60 } 61 62 // Supported constructors: 63 // WebGL<T>Array(n) where n is an integer: 64 // -- create an empty array of n elements 65 // WebGL<T>Array(arr) where arr is an array: 66 // -- create a WebGL<T>Array containing the contents of "arr" 67 // WebGL<T>Array(buf, offset, length) 68 // -- create a WebGL<T>Array pointing to the WebGLArrayBuffer 69 // "buf", starting at the specified offset, for the given 70 // length 71 72 // See whether the first argument is a WebGLArrayBuffer. 73 if (V8WebGLArrayBuffer::HasInstance(args[0])) { 74 if (argLen > 3) 75 return throwError("Wrong number of arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)"); 76 77 WebGLArrayBuffer* buf = V8WebGLArrayBuffer::toNative(args[0]->ToObject()); 78 if (buf == NULL) 79 return throwError("Could not convert argument 0 to a WebGLArrayBuffer"); 80 bool ok; 81 int offset = 0; 82 if (argLen > 1) { 83 offset = toInt32(args[1], ok); 84 if (!ok) 85 return throwError("Could not convert argument 1 to an integer"); 86 } 87 int length = buf->byteLength() - offset; 88 if (argLen > 2) { 89 length = toInt32(args[2], ok); 90 if (!ok) 91 return throwError("Could not convert argument 2 to an integer"); 92 } 93 if (length < 0) 94 return throwError("Length / offset out of range"); 95 96 RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length); 97 if (array == NULL) 98 return throwError("Invalid arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)"); 99 // Transform the holder into a wrapper object for the array. 100 V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get()); 101 V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(), 102 classIndex, 103 array.get()->baseAddress(), 104 array.get()->length()); 105 return toV8(array.release(), args.Holder()); 106 } 107 108 int len = 0; 109 v8::Handle<v8::Object> srcArray; 110 if (argLen != 1) 111 return throwError("Wrong number of arguments to new WebGL<T>Array(int / array)"); 112 113 if (args[0]->IsInt32()) { 114 len = toInt32(args[0]); 115 } else if (args[0]->IsObject()) { 116 srcArray = args[0]->ToObject(); 117 if (srcArray.IsEmpty()) 118 return throwError("Could not convert argument 0 to an object"); 119 len = toInt32(srcArray->Get(v8::String::New("length"))); 120 } else 121 return throwError("Could not convert argument 0 to either an int32 or an object"); 122 123 RefPtr<ArrayClass> array = ArrayClass::create(len); 124 if (!srcArray.IsEmpty()) { 125 // Need to copy the incoming array into the newly created WebGLArray. 126 for (int i = 0; i < len; i++) { 127 v8::Local<v8::Value> val = srcArray->Get(v8::Integer::New(i)); 128 array->set(i, val->NumberValue()); 129 } 130 } 131 132 // Transform the holder into a wrapper object for the array. 133 V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get()); 134 V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(), 135 classIndex, 136 array.get()->baseAddress(), 137 array.get()->length()); 138 return toV8(array.release(), args.Holder()); 139 } 140 141 template <class T, typename ElementType> 142 v8::Handle<v8::Value> getWebGLArrayElement(const v8::Arguments& args, 143 V8ClassIndex::V8WrapperType wrapperType) 144 { 145 if (args.Length() != 1) { 146 V8Proxy::setDOMException(SYNTAX_ERR); 147 return notHandledByInterceptor(); 148 } 149 bool ok; 150 uint32_t index = toInt32(args[0], ok); 151 if (!ok) { 152 V8Proxy::setDOMException(SYNTAX_ERR); 153 return notHandledByInterceptor(); 154 } 155 T* array = reinterpret_cast<T*>(args.Holder()->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); 156 if (index >= array->length()) 157 return v8::Undefined(); 158 ElementType result; 159 if (!array->get(index, result)) 160 return v8::Undefined(); 161 return v8::Number::New(result); 162 } 163 164 template <class T> 165 v8::Handle<v8::Value> setWebGLArrayFromArray(T* webGLArray, const v8::Arguments& args) 166 { 167 if (args[0]->IsObject()) { 168 // void set(in sequence<long> array, [Optional] in unsigned long offset); 169 v8::Local<v8::Object> array = args[0]->ToObject(); 170 uint32_t offset = 0; 171 if (args.Length() == 2) 172 offset = toInt32(args[1]); 173 uint32_t length = toInt32(array->Get(v8::String::New("length"))); 174 if (offset + length > webGLArray->length()) 175 V8Proxy::setDOMException(INDEX_SIZE_ERR); 176 else 177 for (uint32_t i = 0; i < length; i++) 178 webGLArray->set(offset + i, array->Get(v8::Integer::New(i))->NumberValue()); 179 } 180 181 return v8::Undefined(); 182 } 183 184 template <class CPlusPlusArrayType, class JavaScriptWrapperArrayType> 185 v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, 186 V8ClassIndex::V8WrapperType wrapperType) 187 { 188 if (args.Length() < 1 || args.Length() > 2) { 189 V8Proxy::setDOMException(SYNTAX_ERR); 190 return notHandledByInterceptor(); 191 } 192 193 CPlusPlusArrayType* array = JavaScriptWrapperArrayType::toNative(args.Holder()); 194 195 if (args.Length() == 2 && args[0]->IsInt32()) { 196 // void set(in unsigned long index, in {long|float} value); 197 uint32_t index = toInt32(args[0]); 198 array->set(index, args[1]->NumberValue()); 199 return v8::Undefined(); 200 } 201 202 if (JavaScriptWrapperArrayType::HasInstance(args[0])) { 203 // void set(in WebGL<T>Array array, [Optional] in unsigned long offset); 204 CPlusPlusArrayType* src = JavaScriptWrapperArrayType::toNative(args[0]->ToObject()); 205 uint32_t offset = 0; 206 if (args.Length() == 2) 207 offset = toInt32(args[1]); 208 ExceptionCode ec = 0; 209 array->set(src, offset, ec); 210 V8Proxy::setDOMException(ec); 211 return v8::Undefined(); 212 } 213 214 return setWebGLArrayFromArray(array, args); 215 } 216 217 } 218 219 #endif // ENABLE(3D_CANVAS) 220