| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009, 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2009, 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 namespace WebCore { | 42 namespace WebCore { |
| 43 | 43 |
| 44 const char tooLargeSize[] = "Size is too large (or is negative)."; | 44 const char tooLargeSize[] = "Size is too large (or is negative)."; |
| 45 const char outOfRangeLengthAndOffset[] = "Index is out of range."; | 45 const char outOfRangeLengthAndOffset[] = "Index is out of range."; |
| 46 | 46 |
| 47 // Copy the elements from the source array to the typed destination array. | 47 // Copy the elements from the source array to the typed destination array. |
| 48 // Returns true if it succeeded, otherwise returns false. | 48 // Returns true if it succeeded, otherwise returns false. |
| 49 bool copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcAr
ray, uint32_t length, uint32_t offset, v8::Isolate*); | 49 bool copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcAr
ray, uint32_t length, uint32_t offset, v8::Isolate*); |
| 50 | 50 |
| 51 template<class ArrayClass> | 51 template<class ArrayClass> |
| 52 v8::Handle<v8::Value> wrapArrayBufferView(const v8::Arguments& args, WrapperType
Info* type, ArrayClass array, v8::ExternalArrayType arrayType, bool hasIndexer) | 52 void wrapArrayBufferView(const v8::FunctionCallbackInfo<v8::Value>& args, Wrappe
rTypeInfo* type, ArrayClass array, v8::ExternalArrayType arrayType, bool hasInde
xer) |
| 53 { | 53 { |
| 54 // Transform the holder into a wrapper object for the array. | 54 // Transform the holder into a wrapper object for the array. |
| 55 ASSERT(!hasIndexer || static_cast<int32_t>(array.get()->length()) >= 0); | 55 ASSERT(!hasIndexer || static_cast<int32_t>(array.get()->length()) >= 0); |
| 56 if (hasIndexer) | 56 if (hasIndexer) |
| 57 args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->base
Address(), arrayType, array.get()->length()); | 57 args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->base
Address(), arrayType, array.get()->length()); |
| 58 v8::Handle<v8::Object> wrapper = args.Holder(); | 58 v8::Handle<v8::Object> wrapper = args.Holder(); |
| 59 V8DOMWrapper::associateObjectWithWrapper(array.release(), type, wrapper, arg
s.GetIsolate(), WrapperConfiguration::Independent); | 59 V8DOMWrapper::associateObjectWithWrapper(array.release(), type, wrapper, arg
s.GetIsolate(), WrapperConfiguration::Independent); |
| 60 return wrapper; | 60 args.GetReturnValue().Set(wrapper); |
| 61 } | 61 } |
| 62 | 62 |
| 63 // Template function used by the ArrayBufferView*Constructor callbacks. | 63 // Template function used by the ArrayBufferView*Constructor callbacks. |
| 64 template<class ArrayClass, class ElementType> | 64 template<class ArrayClass, class ElementType> |
| 65 v8::Handle<v8::Value> constructWebGLArrayWithArrayBufferArgument(const v8::Argum
ents& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType, bool hasInde
xer) | 65 void constructWebGLArrayWithArrayBufferArgument(const v8::FunctionCallbackInfo<v
8::Value>& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType, bool ha
sIndexer) |
| 66 { | 66 { |
| 67 ArrayBuffer* buf = V8ArrayBuffer::toNative(args[0]->ToObject()); | 67 ArrayBuffer* buf = V8ArrayBuffer::toNative(args[0]->ToObject()); |
| 68 if (!buf) | 68 if (!buf) { |
| 69 return throwTypeError("Could not convert argument 0 to a ArrayBuffer", a
rgs.GetIsolate()); | 69 throwTypeError("Could not convert argument 0 to a ArrayBuffer", args.Get
Isolate()); |
| 70 return; |
| 71 } |
| 70 bool ok; | 72 bool ok; |
| 71 uint32_t offset = 0; | 73 uint32_t offset = 0; |
| 72 int argLen = args.Length(); | 74 int argLen = args.Length(); |
| 73 if (argLen > 1) { | 75 if (argLen > 1) { |
| 74 offset = toUInt32(args[1], ok); | 76 offset = toUInt32(args[1], ok); |
| 75 if (!ok) | 77 if (!ok) { |
| 76 return throwTypeError("Could not convert argument 1 to a number", ar
gs.GetIsolate()); | 78 throwTypeError("Could not convert argument 1 to a number", args.GetI
solate()); |
| 79 return; |
| 80 } |
| 77 } | 81 } |
| 78 uint32_t length = 0; | 82 uint32_t length = 0; |
| 79 if (argLen > 2) { | 83 if (argLen > 2) { |
| 80 length = toUInt32(args[2], ok); | 84 length = toUInt32(args[2], ok); |
| 81 if (!ok) | 85 if (!ok) { |
| 82 return throwTypeError("Could not convert argument 2 to a number", ar
gs.GetIsolate()); | 86 throwTypeError("Could not convert argument 2 to a number", args.GetI
solate()); |
| 87 return; |
| 88 } |
| 83 } else { | 89 } else { |
| 84 if ((buf->byteLength() - offset) % sizeof(ElementType)) | 90 if ((buf->byteLength() - offset) % sizeof(ElementType)) { |
| 85 return throwError(v8RangeError, "ArrayBuffer length minus the byteOf
fset is not a multiple of the element size.", args.GetIsolate()); | 91 throwError(v8RangeError, "ArrayBuffer length minus the byteOffset is
not a multiple of the element size.", args.GetIsolate()); |
| 92 return; |
| 93 } |
| 86 length = (buf->byteLength() - offset) / sizeof(ElementType); | 94 length = (buf->byteLength() - offset) / sizeof(ElementType); |
| 87 } | 95 } |
| 88 | 96 |
| 89 if (static_cast<int32_t>(length) < 0) | 97 if (static_cast<int32_t>(length) < 0) { |
| 90 return throwError(v8RangeError, tooLargeSize, args.GetIsolate()); | 98 throwError(v8RangeError, tooLargeSize, args.GetIsolate()); |
| 99 return; |
| 100 } |
| 91 | 101 |
| 92 RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length); | 102 RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length); |
| 93 if (!array) | 103 if (!array) { |
| 94 return throwError(v8RangeError, tooLargeSize, args.GetIsolate()); | 104 throwError(v8RangeError, tooLargeSize, args.GetIsolate()); |
| 105 return; |
| 106 } |
| 95 | 107 |
| 96 return wrapArrayBufferView(args, type, array, arrayType, hasIndexer); | 108 wrapArrayBufferView(args, type, array, arrayType, hasIndexer); |
| 97 } | 109 } |
| 98 | 110 |
| 99 // Template function used by the ArrayBufferView*Constructor callbacks. | 111 // Template function used by the ArrayBufferView*Constructor callbacks. |
| 100 template<class ArrayClass, class JavaScriptWrapperArrayType, class ElementType> | 112 template<class ArrayClass, class JavaScriptWrapperArrayType, class ElementType> |
| 101 v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, WrapperType
Info* type, v8::ExternalArrayType arrayType) | 113 void constructWebGLArray(const v8::FunctionCallbackInfo<v8::Value>& args, Wrappe
rTypeInfo* type, v8::ExternalArrayType arrayType) |
| 102 { | 114 { |
| 103 if (!args.IsConstructCall()) | 115 if (!args.IsConstructCall()) { |
| 104 return throwTypeError("DOM object constructor cannot be called as a func
tion.", args.GetIsolate()); | 116 throwTypeError("DOM object constructor cannot be called as a function.",
args.GetIsolate()); |
| 117 return; |
| 118 } |
| 105 | 119 |
| 106 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) | 120 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) { |
| 107 return args.Holder(); | 121 args.GetReturnValue().Set(args.Holder()); |
| 122 return; |
| 123 } |
| 108 | 124 |
| 109 int argLen = args.Length(); | 125 int argLen = args.Length(); |
| 110 if (!argLen) { | 126 if (!argLen) { |
| 111 // This happens when we return a previously constructed | 127 // This happens when we return a previously constructed |
| 112 // ArrayBufferView, e.g. from the call to <Type>Array.subset(). | 128 // ArrayBufferView, e.g. from the call to <Type>Array.subset(). |
| 113 // The V8DOMWrapper will set the internal pointer in the | 129 // The V8DOMWrapper will set the internal pointer in the |
| 114 // created object. Unfortunately it doesn't look like it's | 130 // created object. Unfortunately it doesn't look like it's |
| 115 // possible to distinguish between this case and that where | 131 // possible to distinguish between this case and that where |
| 116 // the user calls "new <Type>Array()" from JavaScript. We must | 132 // the user calls "new <Type>Array()" from JavaScript. We must |
| 117 // construct an empty view to avoid crashes when fetching the | 133 // construct an empty view to avoid crashes when fetching the |
| 118 // length. | 134 // length. |
| 119 RefPtr<ArrayClass> array = ArrayClass::create(0); | 135 RefPtr<ArrayClass> array = ArrayClass::create(0); |
| 120 // Do not call SetIndexedPropertiesToExternalArrayData on this | 136 // Do not call SetIndexedPropertiesToExternalArrayData on this |
| 121 // object. Not only is there no point from a performance | 137 // object. Not only is there no point from a performance |
| 122 // perspective, but doing so causes errors in the subset() case. | 138 // perspective, but doing so causes errors in the subset() case. |
| 123 return wrapArrayBufferView(args, type, array, arrayType, false); | 139 wrapArrayBufferView(args, type, array, arrayType, false); |
| 140 return; |
| 124 } | 141 } |
| 125 | 142 |
| 126 // Supported constructors: | 143 // Supported constructors: |
| 127 // WebGL<T>Array(n) where n is an integer: | 144 // WebGL<T>Array(n) where n is an integer: |
| 128 // -- create an empty array of n elements | 145 // -- create an empty array of n elements |
| 129 // WebGL<T>Array(arr) where arr is an array: | 146 // WebGL<T>Array(arr) where arr is an array: |
| 130 // -- create a WebGL<T>Array containing the contents of "arr" | 147 // -- create a WebGL<T>Array containing the contents of "arr" |
| 131 // WebGL<T>Array(buf, offset, length) | 148 // WebGL<T>Array(buf, offset, length) |
| 132 // -- create a WebGL<T>Array pointing to the ArrayBuffer | 149 // -- create a WebGL<T>Array pointing to the ArrayBuffer |
| 133 // "buf", starting at the specified offset, for the given | 150 // "buf", starting at the specified offset, for the given |
| 134 // length | 151 // length |
| 135 | 152 |
| 136 if (args[0]->IsNull()) { | 153 if (args[0]->IsNull()) { |
| 137 // Invalid first argument | 154 // Invalid first argument |
| 138 return throwTypeError(0, args.GetIsolate()); | 155 throwTypeError(0, args.GetIsolate()); |
| 156 return; |
| 139 } | 157 } |
| 140 | 158 |
| 141 // See whether the first argument is a ArrayBuffer. | 159 // See whether the first argument is a ArrayBuffer. |
| 142 if (V8ArrayBuffer::HasInstance(args[0], args.GetIsolate(), worldType(args.Ge
tIsolate()))) | 160 if (V8ArrayBuffer::HasInstance(args[0], args.GetIsolate(), worldType(args.Ge
tIsolate()))) { |
| 143 return constructWebGLArrayWithArrayBufferArgument<ArrayClass, ElementType>
(args, type, arrayType, true); | 161 constructWebGLArrayWithArrayBufferArgument<ArrayClass, ElementType>(args
, type, arrayType, true); |
| 162 return; |
| 163 } |
| 144 | 164 |
| 145 // See whether the first argument is the same type as impl. In that case, | 165 // See whether the first argument is the same type as impl. In that case, |
| 146 // we can simply memcpy data from source to impl. | 166 // we can simply memcpy data from source to impl. |
| 147 if (JavaScriptWrapperArrayType::HasInstance(args[0], args.GetIsolate(), worl
dType(args.GetIsolate()))) { | 167 if (JavaScriptWrapperArrayType::HasInstance(args[0], args.GetIsolate(), worl
dType(args.GetIsolate()))) { |
| 148 ArrayClass* source = JavaScriptWrapperArrayType::toNative(args[0]->ToObj
ect()); | 168 ArrayClass* source = JavaScriptWrapperArrayType::toNative(args[0]->ToObj
ect()); |
| 149 uint32_t length = source->length(); | 169 uint32_t length = source->length(); |
| 150 | 170 |
| 151 if (static_cast<int32_t>(length) < 0) | 171 if (static_cast<int32_t>(length) < 0) { |
| 152 return throwError(v8RangeError, tooLargeSize, args.GetIsolate()); | 172 throwError(v8RangeError, tooLargeSize, args.GetIsolate()); |
| 173 return; |
| 174 } |
| 153 | 175 |
| 154 RefPtr<ArrayClass> array = ArrayClass::createUninitialized(length); | 176 RefPtr<ArrayClass> array = ArrayClass::createUninitialized(length); |
| 155 if (!array.get()) | 177 if (!array.get()) { |
| 156 return throwError(v8RangeError, tooLargeSize, args.GetIsolate()); | 178 throwError(v8RangeError, tooLargeSize, args.GetIsolate()); |
| 179 return; |
| 180 } |
| 157 | 181 |
| 158 array->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserv
er::instance()); | 182 array->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserv
er::instance()); |
| 159 v8::V8::AdjustAmountOfExternalAllocatedMemory(array->byteLength()); | 183 v8::V8::AdjustAmountOfExternalAllocatedMemory(array->byteLength()); |
| 160 | 184 |
| 161 memcpy(array->baseAddress(), source->baseAddress(), length * sizeof(Elem
entType)); | 185 memcpy(array->baseAddress(), source->baseAddress(), length * sizeof(Elem
entType)); |
| 162 | 186 |
| 163 return wrapArrayBufferView(args, type, array, arrayType, true); | 187 wrapArrayBufferView(args, type, array, arrayType, true); |
| 188 return; |
| 164 } | 189 } |
| 165 | 190 |
| 166 uint32_t len = 0; | 191 uint32_t len = 0; |
| 167 v8::Handle<v8::Object> srcArray; | 192 v8::Handle<v8::Object> srcArray; |
| 168 bool doInstantiation = false; | 193 bool doInstantiation = false; |
| 169 | 194 |
| 170 if (args[0]->IsObject()) { | 195 if (args[0]->IsObject()) { |
| 171 srcArray = args[0]->ToObject(); | 196 srcArray = args[0]->ToObject(); |
| 172 if (srcArray.IsEmpty()) | 197 if (srcArray.IsEmpty()) { |
| 173 return throwTypeError("Could not convert argument 0 to an array", ar
gs.GetIsolate()); | 198 throwTypeError("Could not convert argument 0 to an array", args.GetI
solate()); |
| 199 return; |
| 200 } |
| 174 v8::Local<v8::Value> val = srcArray->Get(v8::String::NewSymbol("length")
); | 201 v8::Local<v8::Value> val = srcArray->Get(v8::String::NewSymbol("length")
); |
| 175 if (val.IsEmpty()) { | 202 if (val.IsEmpty()) { |
| 176 // Exception thrown during fetch of length property. | 203 // Exception thrown during fetch of length property. |
| 177 return v8Undefined(); | 204 return; |
| 178 } | 205 } |
| 179 len = toUInt32(val); | 206 len = toUInt32(val); |
| 180 doInstantiation = true; | 207 doInstantiation = true; |
| 181 } else { | 208 } else { |
| 182 bool ok = false; | 209 bool ok = false; |
| 183 int32_t tempLength = toInt32(args[0], ok); // NaN/+inf/-inf returns 0, t
his is intended by WebIDL | 210 int32_t tempLength = toInt32(args[0], ok); // NaN/+inf/-inf returns 0, t
his is intended by WebIDL |
| 184 if (ok && tempLength >= 0) { | 211 if (ok && tempLength >= 0) { |
| 185 len = static_cast<uint32_t>(tempLength); | 212 len = static_cast<uint32_t>(tempLength); |
| 186 doInstantiation = true; | 213 doInstantiation = true; |
| 187 } | 214 } |
| 188 } | 215 } |
| 189 | 216 |
| 190 if (static_cast<int32_t>(len) < 0) | 217 if (static_cast<int32_t>(len) < 0) { |
| 191 return throwError(v8RangeError, tooLargeSize, args.GetIsolate()); | 218 throwError(v8RangeError, tooLargeSize, args.GetIsolate()); |
| 219 return; |
| 220 } |
| 192 | 221 |
| 193 RefPtr<ArrayClass> array; | 222 RefPtr<ArrayClass> array; |
| 194 if (doInstantiation) { | 223 if (doInstantiation) { |
| 195 if (srcArray.IsEmpty()) | 224 if (srcArray.IsEmpty()) |
| 196 array = ArrayClass::create(len); | 225 array = ArrayClass::create(len); |
| 197 else | 226 else |
| 198 array = ArrayClass::createUninitialized(len); | 227 array = ArrayClass::createUninitialized(len); |
| 199 } | 228 } |
| 200 | 229 |
| 201 if (!array.get()) | 230 if (!array.get()) { |
| 202 return throwError(v8RangeError, tooLargeSize, args.GetIsolate()); | 231 throwError(v8RangeError, tooLargeSize, args.GetIsolate()); |
| 232 return; |
| 233 } |
| 203 | 234 |
| 204 if (doInstantiation) { | 235 if (doInstantiation) { |
| 205 array->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserv
er::instance()); | 236 array->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserv
er::instance()); |
| 206 v8::V8::AdjustAmountOfExternalAllocatedMemory(array->byteLength()); | 237 v8::V8::AdjustAmountOfExternalAllocatedMemory(array->byteLength()); |
| 207 } | 238 } |
| 208 | 239 |
| 209 | 240 |
| 210 // Transform the holder into a wrapper object for the array. | 241 // Transform the holder into a wrapper object for the array. |
| 211 args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddr
ess(), arrayType, array.get()->length()); | 242 args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddr
ess(), arrayType, array.get()->length()); |
| 212 | 243 |
| 213 if (!srcArray.IsEmpty()) { | 244 if (!srcArray.IsEmpty()) { |
| 214 bool copied = copyElements(args.Holder(), srcArray, len, 0, args.GetIsol
ate()); | 245 bool copied = copyElements(args.Holder(), srcArray, len, 0, args.GetIsol
ate()); |
| 215 if (!copied) { | 246 if (!copied) { |
| 216 for (unsigned i = 0; i < len; i++) { | 247 for (unsigned i = 0; i < len; i++) { |
| 217 v8::Local<v8::Value> val = srcArray->Get(i); | 248 v8::Local<v8::Value> val = srcArray->Get(i); |
| 218 if (val.IsEmpty()) { | 249 if (val.IsEmpty()) { |
| 219 // Exception thrown during fetch. | 250 // Exception thrown during fetch. |
| 220 return v8Undefined(); | 251 return; |
| 221 } | 252 } |
| 222 array->set(i, val->NumberValue()); | 253 array->set(i, val->NumberValue()); |
| 223 } | 254 } |
| 224 } | 255 } |
| 225 } | 256 } |
| 226 | 257 |
| 227 v8::Handle<v8::Object> wrapper = args.Holder(); | 258 v8::Handle<v8::Object> wrapper = args.Holder(); |
| 228 V8DOMWrapper::associateObjectWithWrapper(array.release(), type, wrapper, arg
s.GetIsolate(), WrapperConfiguration::Independent); | 259 V8DOMWrapper::associateObjectWithWrapper(array.release(), type, wrapper, arg
s.GetIsolate(), WrapperConfiguration::Independent); |
| 229 return wrapper; | 260 args.GetReturnValue().Set(wrapper); |
| 230 } | 261 } |
| 231 | 262 |
| 232 template <class CPlusPlusArrayType, class JavaScriptWrapperArrayType> | 263 template <class CPlusPlusArrayType, class JavaScriptWrapperArrayType> |
| 233 v8::Handle<v8::Value> setWebGLArrayHelper(const v8::Arguments& args) | 264 v8::Handle<v8::Value> setWebGLArrayHelper(const v8::Arguments& args) |
| 234 { | 265 { |
| 235 if (args.Length() < 1) | 266 if (args.Length() < 1) |
| 236 return throwNotEnoughArgumentsError(args.GetIsolate()); | 267 return throwNotEnoughArgumentsError(args.GetIsolate()); |
| 237 | 268 |
| 238 CPlusPlusArrayType* impl = JavaScriptWrapperArrayType::toNative(args.Holder(
)); | 269 CPlusPlusArrayType* impl = JavaScriptWrapperArrayType::toNative(args.Holder(
)); |
| 239 | 270 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 264 } | 295 } |
| 265 return v8::Undefined(); | 296 return v8::Undefined(); |
| 266 } | 297 } |
| 267 | 298 |
| 268 return throwTypeError("Invalid argument", args.GetIsolate()); | 299 return throwTypeError("Invalid argument", args.GetIsolate()); |
| 269 } | 300 } |
| 270 | 301 |
| 271 } | 302 } |
| 272 | 303 |
| 273 #endif // V8ArrayBufferViewCustom_h | 304 #endif // V8ArrayBufferViewCustom_h |
| OLD | NEW |