Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(350)

Side by Side Diff: Source/bindings/v8/custom/V8ArrayBufferViewCustom.h

Issue 19230002: Use V8 implementation of TypedArrays and DataView in Blink (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebased for relanding Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/bindings/v8/V8Binding.cpp ('k') | Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 19 matching lines...) Expand all
30 30
31 #ifndef V8ArrayBufferViewCustom_h 31 #ifndef V8ArrayBufferViewCustom_h
32 #define V8ArrayBufferViewCustom_h 32 #define V8ArrayBufferViewCustom_h
33 33
34 #include "bindings/v8/V8Binding.h" 34 #include "bindings/v8/V8Binding.h"
35 #include "bindings/v8/V8ObjectConstructor.h" 35 #include "bindings/v8/V8ObjectConstructor.h"
36 #include "bindings/v8/custom/V8ArrayBufferCustom.h" 36 #include "bindings/v8/custom/V8ArrayBufferCustom.h"
37 #include "core/dom/ExceptionCode.h" 37 #include "core/dom/ExceptionCode.h"
38 38
39 #include "wtf/ArrayBuffer.h" 39 #include "wtf/ArrayBuffer.h"
40 #include "wtf/ArrayBufferView.h"
40 41
41 namespace WebCore { 42 namespace WebCore {
42 43
43 const char tooLargeSize[] = "Size is too large (or is negative).";
44 const char outOfRangeLengthAndOffset[] = "Index is out of range.";
45 44
46 // Copy the elements from the source array to the typed destination array. 45 class V8ArrayBufferView {
47 // Returns true if it succeeded, otherwise returns false. 46 public:
48 bool copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcAr ray, uint32_t length, uint32_t offset, v8::Isolate*); 47 static bool HasInstance(v8::Handle<v8::Value> value, v8::Isolate*, WrapperWo rldType)
48 {
49 return value->IsArrayBufferView();
50 }
51 static bool HasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate*)
52 {
53 return value->IsArrayBufferView();
54 }
55 static ArrayBufferView* toNative(v8::Handle<v8::Object>);
49 56
50 template<class JavaScriptWrapperArrayType, class ArrayClass> 57 static inline void* toInternalPointer(ArrayBufferView* impl)
51 void wrapArrayBufferView(const v8::FunctionCallbackInfo<v8::Value>& args, Wrappe rTypeInfo* type, ArrayClass array, v8::ExternalArrayType arrayType, bool hasInde xer) 58 {
52 { 59 return impl;
53 // Transform the holder into a wrapper object for the array.
54 ASSERT(!hasIndexer || static_cast<int32_t>(array.get()->length()) >= 0);
55 if (hasIndexer)
56 args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->base Address(), arrayType, array.get()->length());
57 v8::Handle<v8::Object> wrapper = args.Holder();
58 V8DOMWrapper::associateObjectWithWrapper<JavaScriptWrapperArrayType>(array.r elease(), type, wrapper, args.GetIsolate(), WrapperConfiguration::Independent);
59 args.GetReturnValue().Set(wrapper);
60 }
61
62 // Template function used by the ArrayBufferView*Constructor callbacks.
63 template<class ArrayClass, class ElementType, class JavaScriptWrapperArrayType>
64 void constructWebGLArrayWithArrayBufferArgument(const v8::FunctionCallbackInfo<v 8::Value>& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType, bool ha sIndexer)
65 {
66 ArrayBuffer* buf = V8ArrayBuffer::toNative(args[0]->ToObject());
67 if (!buf) {
68 throwTypeError("Could not convert argument 0 to a ArrayBuffer", args.Get Isolate());
69 return;
70 } 60 }
71 bool ok; 61 };
72 uint32_t offset = 0;
73 int argLen = args.Length();
74 if (argLen > 1) {
75 offset = toUInt32(args[1], ok);
76 if (!ok) {
77 throwTypeError("Could not convert argument 1 to a number", args.GetI solate());
78 return;
79 }
80 }
81 uint32_t length = 0;
82 if (argLen > 2) {
83 length = toUInt32(args[2], ok);
84 if (!ok) {
85 throwTypeError("Could not convert argument 2 to a number", args.GetI solate());
86 return;
87 }
88 } else {
89 if ((buf->byteLength() - offset) % sizeof(ElementType)) {
90 throwError(v8RangeError, "ArrayBuffer length minus the byteOffset is not a multiple of the element size.", args.GetIsolate());
91 return;
92 }
93 length = (buf->byteLength() - offset) / sizeof(ElementType);
94 }
95
96 if (static_cast<int32_t>(length) < 0) {
97 throwError(v8RangeError, tooLargeSize, args.GetIsolate());
98 return;
99 }
100
101 RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length);
102 if (!array) {
103 throwError(v8RangeError, tooLargeSize, args.GetIsolate());
104 return;
105 }
106
107 wrapArrayBufferView<JavaScriptWrapperArrayType>(args, type, array, arrayType , hasIndexer);
108 }
109
110 // Template function used by the ArrayBufferView*Constructor callbacks.
111 template<class ArrayClass, class JavaScriptWrapperArrayType, class ElementType>
112 void constructWebGLArray(const v8::FunctionCallbackInfo<v8::Value>& args, Wrappe rTypeInfo* type, v8::ExternalArrayType arrayType)
113 {
114 if (!args.IsConstructCall()) {
115 throwTypeError("DOM object constructor cannot be called as a function.", args.GetIsolate());
116 return;
117 }
118
119 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
120 args.GetReturnValue().Set(args.Holder());
121 return;
122 }
123
124 int argLen = args.Length();
125 if (!argLen) {
126 // This happens when we return a previously constructed
127 // ArrayBufferView, e.g. from the call to <Type>Array.subset().
128 // The V8DOMWrapper will set the internal pointer in the
129 // created object. Unfortunately it doesn't look like it's
130 // possible to distinguish between this case and that where
131 // the user calls "new <Type>Array()" from JavaScript. We must
132 // construct an empty view to avoid crashes when fetching the
133 // length.
134 RefPtr<ArrayClass> array = ArrayClass::create(0);
135 // Do not call SetIndexedPropertiesToExternalArrayData on this
136 // object. Not only is there no point from a performance
137 // perspective, but doing so causes errors in the subset() case.
138 wrapArrayBufferView<JavaScriptWrapperArrayType>(args, type, array, array Type, false);
139 return;
140 }
141
142 // Supported constructors:
143 // WebGL<T>Array(n) where n is an integer:
144 // -- create an empty array of n elements
145 // WebGL<T>Array(arr) where arr is an array:
146 // -- create a WebGL<T>Array containing the contents of "arr"
147 // WebGL<T>Array(buf, offset, length)
148 // -- create a WebGL<T>Array pointing to the ArrayBuffer
149 // "buf", starting at the specified offset, for the given
150 // length
151
152 if (args[0]->IsNull()) {
153 // Invalid first argument
154 throwTypeError(args.GetIsolate());
155 return;
156 }
157
158 // See whether the first argument is a ArrayBuffer.
159 if (V8ArrayBuffer::HasInstance(args[0], args.GetIsolate(), worldType(args.Ge tIsolate()))) {
160 constructWebGLArrayWithArrayBufferArgument<ArrayClass, ElementType, Java ScriptWrapperArrayType>(args, type, arrayType, true);
161 return;
162 }
163
164 // See whether the first argument is the same type as impl. In that case,
165 // we can simply memcpy data from source to impl.
166 if (JavaScriptWrapperArrayType::HasInstance(args[0], args.GetIsolate(), worl dType(args.GetIsolate()))) {
167 ArrayClass* source = JavaScriptWrapperArrayType::toNative(args[0]->ToObj ect());
168 uint32_t length = source->length();
169
170 if (static_cast<int32_t>(length) < 0) {
171 throwError(v8RangeError, tooLargeSize, args.GetIsolate());
172 return;
173 }
174
175 RefPtr<ArrayClass> array = ArrayClass::createUninitialized(length);
176 if (!array.get()) {
177 throwError(v8RangeError, tooLargeSize, args.GetIsolate());
178 return;
179 }
180
181 array->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserv er::instance());
182 v8::V8::AdjustAmountOfExternalAllocatedMemory(array->byteLength());
183
184 memcpy(array->baseAddress(), source->baseAddress(), length * sizeof(Elem entType));
185
186 wrapArrayBufferView<JavaScriptWrapperArrayType>(args, type, array, array Type, true);
187 return;
188 }
189
190 uint32_t len = 0;
191 v8::Handle<v8::Object> srcArray;
192 bool doInstantiation = false;
193
194 if (args[0]->IsObject()) {
195 srcArray = args[0]->ToObject();
196 if (srcArray.IsEmpty()) {
197 throwTypeError("Could not convert argument 0 to an array", args.GetI solate());
198 return;
199 }
200 v8::Local<v8::Value> val = srcArray->Get(v8::String::NewSymbol("length") );
201 if (val.IsEmpty()) {
202 // Exception thrown during fetch of length property.
203 return;
204 }
205 len = toUInt32(val);
206 doInstantiation = true;
207 } else {
208 bool ok = false;
209 int32_t tempLength = toInt32(args[0], ok); // NaN/+inf/-inf returns 0, t his is intended by WebIDL
210 if (ok && tempLength >= 0) {
211 len = static_cast<uint32_t>(tempLength);
212 doInstantiation = true;
213 }
214 }
215
216 if (static_cast<int32_t>(len) < 0) {
217 throwError(v8RangeError, tooLargeSize, args.GetIsolate());
218 return;
219 }
220
221 RefPtr<ArrayClass> array;
222 if (doInstantiation) {
223 if (srcArray.IsEmpty())
224 array = ArrayClass::create(len);
225 else
226 array = ArrayClass::createUninitialized(len);
227 }
228
229 if (!array.get()) {
230 throwError(v8RangeError, tooLargeSize, args.GetIsolate());
231 return;
232 }
233
234 if (doInstantiation) {
235 array->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserv er::instance());
236 v8::V8::AdjustAmountOfExternalAllocatedMemory(array->byteLength());
237 }
238 62
239 63
240 // Transform the holder into a wrapper object for the array. 64 } // namespace WebCore
241 args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddr ess(), arrayType, array.get()->length());
242
243 if (!srcArray.IsEmpty()) {
244 bool copied = copyElements(args.Holder(), srcArray, len, 0, args.GetIsol ate());
245 if (!copied) {
246 for (unsigned i = 0; i < len; i++) {
247 v8::Local<v8::Value> val = srcArray->Get(i);
248 if (val.IsEmpty()) {
249 // Exception thrown during fetch.
250 return;
251 }
252 array->set(i, val->NumberValue());
253 }
254 }
255 }
256
257 v8::Handle<v8::Object> wrapper = args.Holder();
258 V8DOMWrapper::associateObjectWithWrapper<JavaScriptWrapperArrayType>(array.r elease(), type, wrapper, args.GetIsolate(), WrapperConfiguration::Independent);
259 args.GetReturnValue().Set(wrapper);
260 }
261
262 template <class CPlusPlusArrayType, class JavaScriptWrapperArrayType>
263 void setWebGLArrayHelper(const v8::FunctionCallbackInfo<v8::Value>& args)
264 {
265 if (args.Length() < 1) {
266 throwNotEnoughArgumentsError(args.GetIsolate());
267 return;
268 }
269
270 CPlusPlusArrayType* impl = JavaScriptWrapperArrayType::toNative(args.Holder( ));
271
272 if (JavaScriptWrapperArrayType::HasInstance(args[0], args.GetIsolate(), worl dType(args.GetIsolate()))) {
273 // void set(in WebGL<T>Array array, [Optional] in unsigned long offset);
274 CPlusPlusArrayType* src = JavaScriptWrapperArrayType::toNative(args[0]-> ToObject());
275 uint32_t offset = 0;
276 if (args.Length() == 2)
277 offset = toUInt32(args[1]);
278 if (!impl->set(src, offset)) {
279 throwError(v8RangeError, outOfRangeLengthAndOffset, args.GetIsolate( ));
280 return;
281 }
282 return;
283 }
284
285 if (args[0]->IsObject()) {
286 // void set(in sequence<long> array, [Optional] in unsigned long offset) ;
287 v8::Local<v8::Object> array = args[0]->ToObject();
288 uint32_t offset = 0;
289 if (args.Length() == 2)
290 offset = toUInt32(args[1]);
291 uint32_t length = toUInt32(array->Get(v8::String::NewSymbol("length")));
292 if (!impl->checkInboundData(offset, length)) {
293 throwError(v8RangeError, outOfRangeLengthAndOffset, args.GetIsolate( ));
294 return;
295 }
296 bool copied = copyElements(args.Holder(), array, length, offset, args.Ge tIsolate());
297 if (!copied) {
298 for (uint32_t i = 0; i < length; i++)
299 impl->set(offset + i, array->Get(i)->NumberValue());
300 }
301 return;
302 }
303
304 throwTypeError("Invalid argument", args.GetIsolate());
305 }
306
307 }
308
309 #endif // V8ArrayBufferViewCustom_h 65 #endif // V8ArrayBufferViewCustom_h
OLDNEW
« no previous file with comments | « Source/bindings/v8/V8Binding.cpp ('k') | Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698