OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
274 if (source.IsEmpty()) { | 274 if (source.IsEmpty()) { |
275 return ThrowException(String::New("Error loading file")); | 275 return ThrowException(String::New("Error loading file")); |
276 } | 276 } |
277 if (!ExecuteString(source, String::New(*file), false, true)) { | 277 if (!ExecuteString(source, String::New(*file), false, true)) { |
278 return ThrowException(String::New("Error executing file")); | 278 return ThrowException(String::New("Error executing file")); |
279 } | 279 } |
280 } | 280 } |
281 return Undefined(); | 281 return Undefined(); |
282 } | 282 } |
283 | 283 |
284 static int convertToInt(Local<Value> value_in, TryCatch* try_catch) { | |
Jakob Kummerow
2012/01/11 10:17:53
Rename to convertToUint?
danno
2012/01/11 13:07:41
Done.
| |
285 if (value_in->IsUint32()) { | |
286 return value_in->Uint32Value(); | |
287 } | |
288 | |
289 Local<Value> number = value_in->ToNumber(); | |
290 if (number.IsEmpty()) { | |
291 ASSERT(try_catch->HasCaught()); | |
292 return 0; | |
293 } | |
294 | |
295 ASSERT(number->IsNumber()); | |
296 Local<Int32> int32 = number->ToInt32(); | |
297 if (int32.IsEmpty()) { | |
298 ASSERT(try_catch->HasCaught()); | |
299 return 0; | |
300 } | |
301 int32_t raw_value = int32->Int32Value(); | |
302 if (try_catch->HasCaught()) { | |
303 return 0; | |
304 } | |
305 if (raw_value < 0) { | |
306 ThrowException(String::New("Array length must not be negative.")); | |
307 return 0; | |
308 } | |
309 | |
310 static const int kMaxLength = 0x3fffffff; | |
311 #ifndef V8_SHARED | |
312 ASSERT(kMaxLength == i::ExternalArray::kMaxLength); | |
313 #endif // V8_SHARED | |
314 if (raw_value > static_cast<int32_t>(kMaxLength)) { | |
315 ThrowException( | |
316 String::New("Array length exceeds maximum length.")); | |
317 } | |
318 return static_cast<size_t>(raw_value); | |
319 } | |
320 | |
321 | |
322 const char kArrayBufferReferencePropName[] = "_array_buffer_ref"; | |
323 | |
284 | 324 |
285 Handle<Value> Shell::CreateExternalArray(const Arguments& args, | 325 Handle<Value> Shell::CreateExternalArray(const Arguments& args, |
286 ExternalArrayType type, | 326 ExternalArrayType type, |
287 size_t element_size) { | 327 size_t element_size) { |
288 ASSERT(element_size == 1 || element_size == 2 || element_size == 4 || | 328 ASSERT(element_size == 1 || element_size == 2 || element_size == 4 || |
289 element_size == 8); | 329 element_size == 8); |
290 if (args.Length() != 1) { | 330 TryCatch try_catch; |
291 return ThrowException( | 331 size_t derived_from_element_size = 1; |
292 String::New("Array constructor needs one parameter.")); | 332 if (args[0]->IsNumber()) { |
333 if (args.Length() != 1) { | |
334 return ThrowException( | |
335 String::New("Array constructor with length must have " | |
336 "one parameter.")); | |
337 } | |
338 } else { | |
339 if (args.Length() > 3 || args.Length() == 0) { | |
Jakob Kummerow
2012/01/11 10:17:53
Arguments.operator[] is benign enough to simply re
danno
2012/01/11 13:07:41
Done.
| |
340 return ThrowException( | |
341 String::New("Array constructor from ArrayBuffer must " | |
342 "have 1-3 parameters.")); | |
343 } | |
293 } | 344 } |
294 static const int kMaxLength = 0x3fffffff; | 345 |
295 #ifndef V8_SHARED | 346 Local<Value> length_value = (args.Length() == 1) |
296 ASSERT(kMaxLength == i::ExternalArray::kMaxLength); | 347 ? (args[0]->IsNumber() |
297 #endif // V8_SHARED | 348 ? args[0] |
298 size_t length = 0; | 349 : args[0]->ToObject()->Get(String::New("length"))) |
299 TryCatch try_catch; | 350 : args[2]; |
Jakob Kummerow
2012/01/11 10:17:53
args[2] is optional and could be undefined. As imp
danno
2012/01/11 13:07:41
Done.
| |
300 if (args[0]->IsUint32()) { | 351 int length = convertToInt(length_value, &try_catch); |
301 length = args[0]->Uint32Value(); | 352 if (try_catch.HasCaught()) return try_catch.Exception(); |
302 } else { | 353 |
303 Local<Number> number = args[0]->ToNumber(); | 354 void* data = NULL; |
304 if (number.IsEmpty()) { | 355 if (!args[0]->IsNumber()) { |
305 ASSERT(try_catch.HasCaught()); | 356 Handle<Object> array = args[0]->ToObject(); |
306 return try_catch.Exception(); | 357 data = array->GetIndexedPropertiesExternalArrayData(); |
358 if (data == NULL) { | |
359 return ThrowException( | |
360 String::New("ArrayBuffer doesn't have data")); | |
307 } | 361 } |
308 ASSERT(number->IsNumber()); | 362 derived_from_element_size = |
309 Local<Int32> int32 = number->ToInt32(); | 363 array->Get(String::New("BYTES_PER_ELEMENT"))->ToInt32()->Int32Value(); |
Jakob Kummerow
2012/01/11 10:17:53
My reading of the spec at http://www.khronos.org/r
danno
2012/01/11 13:07:41
Done.
| |
310 if (int32.IsEmpty()) { | 364 length *= derived_from_element_size; |
311 if (try_catch.HasCaught()) { | 365 length /= element_size; |
312 return try_catch.Exception(); | 366 } |
313 } | 367 |
368 size_t offset = 0; | |
369 if (args.Length() > 1) { | |
370 offset = convertToInt(args[1], &try_catch); | |
371 if (try_catch.HasCaught()) return try_catch.Exception(); | |
372 | |
373 if (offset % element_size != 0) { | |
374 return ThrowException( | |
375 String::New("offset must be multiple of element_size")); | |
314 } | 376 } |
315 int32_t raw_length = int32->Int32Value(); | |
316 if (try_catch.HasCaught()) { | |
317 return try_catch.Exception(); | |
318 } | |
319 if (raw_length < 0) { | |
320 return ThrowException(String::New("Array length must not be negative.")); | |
321 } | |
322 if (raw_length > static_cast<int32_t>(kMaxLength)) { | |
323 return ThrowException( | |
324 String::New("Array length exceeds maximum length.")); | |
325 } | |
326 length = static_cast<size_t>(raw_length); | |
327 } | 377 } |
328 if (length > static_cast<size_t>(kMaxLength)) { | 378 |
329 return ThrowException(String::New("Array length exceeds maximum length.")); | |
330 } | |
331 void* data = calloc(length, element_size); | |
332 if (data == NULL) { | |
333 return ThrowException(String::New("Memory allocation failed.")); | |
334 } | |
335 Handle<Object> array = Object::New(); | 379 Handle<Object> array = Object::New(); |
336 Persistent<Object> persistent_array = Persistent<Object>::New(array); | 380 Persistent<Object> persistent_array = Persistent<Object>::New(array); |
337 persistent_array.MakeWeak(data, ExternalArrayWeakCallback); | 381 persistent_array.MakeWeak(data, ExternalArrayWeakCallback); |
338 persistent_array.MarkIndependent(); | 382 persistent_array.MarkIndependent(); |
339 array->SetIndexedPropertiesToExternalArrayData(data, type, | 383 if (data == NULL) { |
340 static_cast<int>(length)); | 384 data = calloc(length, element_size); |
385 if (data == NULL) { | |
386 return ThrowException(String::New("Memory allocation failed.")); | |
387 } | |
388 } else { | |
389 // Hold a reference to the ArrayBuffer so it's buffer doesn't get collected. | |
Jakob Kummerow
2012/01/11 10:17:53
s/it's/its/
danno
2012/01/11 13:07:41
Done.
| |
390 array->Set(String::New(kArrayBufferReferencePropName), args[0], ReadOnly); | |
391 } | |
392 array->SetIndexedPropertiesToExternalArrayData( | |
393 reinterpret_cast<uint8_t*>(data) + offset, type, | |
Jakob Kummerow
2012/01/11 10:17:53
Whoa... please add checks that both |offset| and |
danno
2012/01/11 13:07:41
Done.
| |
394 static_cast<int>(length)); | |
341 array->Set(String::New("length"), | 395 array->Set(String::New("length"), |
342 Int32::New(static_cast<int32_t>(length)), ReadOnly); | 396 Int32::New(static_cast<int32_t>(length)), ReadOnly); |
343 array->Set(String::New("BYTES_PER_ELEMENT"), | 397 array->Set(String::New("BYTES_PER_ELEMENT"), |
344 Int32::New(static_cast<int32_t>(element_size))); | 398 Int32::New(static_cast<int32_t>(element_size))); |
345 return array; | 399 return array; |
346 } | 400 } |
347 | 401 |
348 | 402 |
349 void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) { | 403 void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) { |
350 free(data); | 404 Handle<String> prop_name = String::New(kArrayBufferReferencePropName); |
351 object.Dispose(); | 405 Handle<Object> converted_object = object->ToObject(); |
406 Local<Value> prop_value = converted_object->Get(prop_name); | |
407 if (!prop_value->IsObject()) { | |
408 free(data); | |
409 object.Dispose(); | |
410 } | |
352 } | 411 } |
353 | 412 |
354 | 413 |
414 Handle<Value> Shell::ArrayBuffer(const Arguments& args) { | |
415 return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t)); | |
416 } | |
417 | |
418 | |
355 Handle<Value> Shell::Int8Array(const Arguments& args) { | 419 Handle<Value> Shell::Int8Array(const Arguments& args) { |
356 return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t)); | 420 return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t)); |
357 } | 421 } |
358 | 422 |
359 | 423 |
360 Handle<Value> Shell::Uint8Array(const Arguments& args) { | 424 Handle<Value> Shell::Uint8Array(const Arguments& args) { |
361 return CreateExternalArray(args, kExternalUnsignedByteArray, sizeof(uint8_t)); | 425 return CreateExternalArray(args, kExternalUnsignedByteArray, sizeof(uint8_t)); |
362 } | 426 } |
363 | 427 |
364 | 428 |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 FunctionTemplate::New(ReadLine)); | 750 FunctionTemplate::New(ReadLine)); |
687 global_template->Set(String::New("load"), FunctionTemplate::New(Load)); | 751 global_template->Set(String::New("load"), FunctionTemplate::New(Load)); |
688 global_template->Set(String::New("quit"), FunctionTemplate::New(Quit)); | 752 global_template->Set(String::New("quit"), FunctionTemplate::New(Quit)); |
689 global_template->Set(String::New("version"), FunctionTemplate::New(Version)); | 753 global_template->Set(String::New("version"), FunctionTemplate::New(Version)); |
690 global_template->Set(String::New("enableProfiler"), | 754 global_template->Set(String::New("enableProfiler"), |
691 FunctionTemplate::New(EnableProfiler)); | 755 FunctionTemplate::New(EnableProfiler)); |
692 global_template->Set(String::New("disableProfiler"), | 756 global_template->Set(String::New("disableProfiler"), |
693 FunctionTemplate::New(DisableProfiler)); | 757 FunctionTemplate::New(DisableProfiler)); |
694 | 758 |
695 // Bind the handlers for external arrays. | 759 // Bind the handlers for external arrays. |
760 global_template->Set(String::New("ArrayBuffer"), | |
761 FunctionTemplate::New(ArrayBuffer)); | |
696 global_template->Set(String::New("Int8Array"), | 762 global_template->Set(String::New("Int8Array"), |
697 FunctionTemplate::New(Int8Array)); | 763 FunctionTemplate::New(Int8Array)); |
698 global_template->Set(String::New("Uint8Array"), | 764 global_template->Set(String::New("Uint8Array"), |
699 FunctionTemplate::New(Uint8Array)); | 765 FunctionTemplate::New(Uint8Array)); |
700 global_template->Set(String::New("Int16Array"), | 766 global_template->Set(String::New("Int16Array"), |
701 FunctionTemplate::New(Int16Array)); | 767 FunctionTemplate::New(Int16Array)); |
702 global_template->Set(String::New("Uint16Array"), | 768 global_template->Set(String::New("Uint16Array"), |
703 FunctionTemplate::New(Uint16Array)); | 769 FunctionTemplate::New(Uint16Array)); |
704 global_template->Set(String::New("Int32Array"), | 770 global_template->Set(String::New("Int32Array"), |
705 FunctionTemplate::New(Int32Array)); | 771 FunctionTemplate::New(Int32Array)); |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1393 } | 1459 } |
1394 | 1460 |
1395 } // namespace v8 | 1461 } // namespace v8 |
1396 | 1462 |
1397 | 1463 |
1398 #ifndef GOOGLE3 | 1464 #ifndef GOOGLE3 |
1399 int main(int argc, char* argv[]) { | 1465 int main(int argc, char* argv[]) { |
1400 return v8::Shell::Main(argc, argv); | 1466 return v8::Shell::Main(argc, argv); |
1401 } | 1467 } |
1402 #endif | 1468 #endif |
OLD | NEW |