193836df42282919441bbe793053c39ac5be19c1
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / utils / v8-utils.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // HEADER
19 #include "v8-utils.h"
20
21 // EXTERNAL INCLUDES
22 #include <iostream>
23 #include <fstream>
24 #include <sstream>
25 #include <dali/integration-api/debug.h>
26
27 // INTERNAL INCLUDES
28 #include <object/property-value-wrapper.h>
29 #include <actors/actor-wrapper.h>
30 #include <object/handle-wrapper.h>
31 #include <image/image-wrapper.h>
32 #include <render-tasks/render-task-wrapper.h>
33 #include <object/property-value-wrapper.h>
34
35
36 /**
37  * Similar to DALI_LOG_ERROR except the PRETTY_FUNCTION
38  * is removed because it makes no sense for scripting errors.
39  */
40 #define DALI_LOG_SCRIPT_ERROR(format, args...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError, format, ## args)
41
42 namespace Dali
43 {
44
45 namespace V8Plugin
46 {
47
48 namespace V8Utils
49 {
50
51 void Log(const v8::FunctionCallbackInfo< v8::Value >& args)
52 {
53   v8::HandleScope handleScope( args.GetIsolate());
54
55   bool first = true;
56   for (int i = 0; i < args.Length(); i++)
57   {
58     if (first)
59     {
60       first = false;
61     }
62     else
63     {
64       std::cout << " ";
65     }
66     v8::String::Utf8Value utf8_value( args[i] );
67     std::cout << *utf8_value << "\n";
68   }
69 }
70
71 void LogError(const v8::FunctionCallbackInfo< v8::Value >& args)
72 {
73   v8::HandleScope handleScope( args.GetIsolate());
74   std::string output;
75   bool first = true;
76   for (int i = 0; i < args.Length(); i++)
77   {
78     if (first)
79     {
80       first = false;
81     }
82     else
83     {
84       output +=" ";
85     }
86     v8::String::Utf8Value utf8_value( args[i] );
87     output += *utf8_value;
88     output +="\n";
89   }
90   DALI_LOG_ERROR_NOFN( "JavaScript: %s",output.c_str() );
91 }
92
93 void GetFileContents(const std::string &fileName, std::string& contents)
94 {
95    std::ifstream t(fileName.c_str());
96    contents = std::string((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
97 };
98
99 void GetFileDirectory( const std::string& fileName, std::string& directory )
100 {
101   directory = "";
102
103   // get the position of the last slash
104   size_t pos = fileName.find_last_of("\\/");
105
106   // if it doesn't exist, return nothing
107   if( (std::string::npos == pos ) )
108   {
109     return;
110   }
111   else
112   {
113     // check an edge case where the string ends in a forward slash "mydir/"
114     if( (pos+1) < fileName.length() )
115     {
116       directory = fileName.substr(0, pos+1);
117       return;
118     }
119   }
120 }
121
122 void GetFileName( const std::string& fullPathName, std::string& fileName )
123 {
124   // look for last slash
125   size_t pos = fullPathName.find_last_of("\\/");
126
127   if( std::string::npos == pos )
128   {
129     fileName = fullPathName;
130   }
131   else
132   {
133     fileName = fullPathName.substr(pos,fileName.length());
134   }
135 }
136
137 void GetModuleName( const std::string& fileName, std::string& moduleName )
138 {
139   std::string fileNameNoPath;
140    GetFileName( fileName , fileNameNoPath );
141   size_t pos = fileNameNoPath.find_last_of(".");
142   if( std::string::npos == pos )
143   {
144     moduleName = fileNameNoPath;
145   }
146   else
147   {
148     moduleName = fileName.substr(0, pos );
149   }
150 }
151
152 bool IsPropertyMapIdentical(Property::Map map1, Property::Map map2)
153 {
154   bool dirty = false;
155
156   // Compare number of properties
157   if ( map1.Count() != map2.Count() )
158   {
159     dirty = true;
160   }
161   else
162   {
163     for ( unsigned int i = 0, count = map1.Count(); i < count; ++i )
164     {
165       // Compare the key first
166       if(map1.GetKey(i) != map2.GetKey(i))
167       {
168         dirty = true;
169       }
170       else
171       {
172         Property::Value& value = map1.GetValue(i);
173         Property::Value& newValue = map2.GetValue(i);
174
175         // Compare the value type
176         if(value.GetType() != newValue.GetType())
177         {
178           dirty = true;
179         }
180         else
181         {
182           // Compare the value
183           switch( value.GetType() )
184           {
185             case Property::BOOLEAN:
186             {
187               dirty = ( value.Get<bool>() != newValue.Get<bool>() );
188               break;
189             }
190             case Property::FLOAT:
191             {
192               dirty = ( value.Get<float>() != newValue.Get<float>() );
193               break;
194             }
195             case Property::INTEGER:
196             {
197               dirty = ( value.Get<int>() != newValue.Get<int>() );
198               break;
199             }
200             case Property::RECTANGLE:
201             {
202               dirty = ( value.Get< Rect<int> >() != newValue.Get< Rect<int> >() );
203               break;
204             }
205             case Property::VECTOR2:
206             {
207               dirty = ( value.Get<Vector2>() != newValue.Get<Vector2>() );
208               break;
209             }
210             case Property::VECTOR3:
211             {
212               dirty = ( value.Get<Vector3>() != newValue.Get<Vector3>() );
213               break;
214             }
215             case Property::VECTOR4:
216             {
217               dirty = ( value.Get<Vector4>() != newValue.Get<Vector4>() );
218               break;
219             }
220             case Property::MATRIX3:
221             {
222               dirty = ( value.Get<Matrix3>() != newValue.Get<Matrix3>() );
223               break;
224             }
225             case Property::MATRIX:
226             {
227               dirty = ( value.Get<Matrix>() != newValue.Get<Matrix>() );
228               break;
229             }
230             case Property::ROTATION:
231             {
232               dirty = ( value.Get<Quaternion>() != newValue.Get<Quaternion>() );
233               break;
234             }
235             case Property::STRING:
236             {
237               dirty = ( value.Get<std::string>() != newValue.Get<std::string>() );
238               break;
239             }
240             case Property::MAP:
241             {
242               dirty = ( !IsPropertyMapIdentical( value.Get<Property::Map>(), newValue.Get<Property::Map>() ) );
243               break;
244             }
245             default:
246             {
247               break;
248             }
249           }
250         }
251       }
252
253       if(dirty)
254       {
255         // Different already, no need any further comparison
256         break;
257       }
258     }
259   }
260
261   return !dirty;
262 }
263
264 void ReportException(  v8::Isolate* isolate, v8::TryCatch* tryCatch)
265 {
266   v8::HandleScope handleScope( isolate );
267
268   v8::String::Utf8Value exception(tryCatch->Exception());
269   v8::Handle<v8::Message> message   = tryCatch->Message();
270
271   if (message.IsEmpty())
272   {
273     // V8 didn't provide any extra information about this error; just
274     // print the exception.
275     DALI_LOG_SCRIPT_ERROR("%s\n", *exception);
276   }
277   else
278   {
279
280     // Print (filename):(line number): (message).
281     v8::String::Utf8Value filename(message->GetScriptResourceName());
282
283     DALI_LOG_SCRIPT_ERROR("\n\n====== Error found in JavaScript: ========= \n");
284
285
286     int linenum = message->GetLineNumber();
287     DALI_LOG_SCRIPT_ERROR("File: %s\n", *filename, linenum, *exception);
288
289      DALI_LOG_SCRIPT_ERROR("Error: :%s\n", *exception );
290      DALI_LOG_SCRIPT_ERROR("Line: :%i\n",  linenum );
291
292     // Print line of source code.
293     v8::String::Utf8Value sourceline(message->GetSourceLine());
294
295     DALI_LOG_SCRIPT_ERROR("Source: %s\n", *sourceline);
296
297     // Print wavy underline (GetUnderline is deprecated).
298
299     std::stringstream msg;
300
301     int start = message->GetStartColumn();
302     for (int i = 0; i < start; i++)
303     {
304       msg << " ";
305     }
306     int end = message->GetEndColumn();
307     for (int i = start; i < end; i++)
308     {
309       msg << "↑";
310     }
311
312     DALI_LOG_SCRIPT_ERROR("        %s\n", msg.str().c_str());
313
314     v8::String::Utf8Value stack_trace(tryCatch->StackTrace());
315     if (stack_trace.length() > 0)
316     {
317       DALI_LOG_SCRIPT_ERROR("%s\n", *stack_trace);
318     }
319     DALI_LOG_SCRIPT_ERROR("\n=========================================== \n");
320
321   }
322 }
323
324 std::string GetJavaScriptFunctionName( const char* functionName  )
325 {
326   // @todo if we are 100% decided on lower case, go through
327   // every api and manually change the function names to lower case first character
328   std::string name( functionName );
329   name[0]=tolower( functionName[0] );
330   return name;
331 }
332
333 void Version(const v8::FunctionCallbackInfo< v8::Value >& args)
334 {
335   v8::HandleScope handleScope( args.GetIsolate());
336
337   v8::Handle<v8::String>  ver = v8::String::NewFromUtf8(args.GetIsolate(), v8::V8::GetVersion());
338
339   args.GetReturnValue().Set(ver);
340 }
341
342
343 std::string v8StringToStdString( const v8::Handle<v8::Value>& value )
344 {
345   v8::String::Utf8Value utf8(value);
346   return std::string(*utf8);
347 }
348
349
350 std::string PropertyNameToJavaScriptName(const std::string& hyphenatedName)
351 {
352   std::string ret;
353
354   ret.reserve(hyphenatedName.size());
355
356   bool capitlizeNext = false ;
357   for(unsigned int i = 0; i < hyphenatedName.size(); ++i)
358   {
359     char c = hyphenatedName[i];
360     if(c == '-')
361     {
362       capitlizeNext = true;
363     }
364     else
365     {
366       if(capitlizeNext)
367       {
368         ret.push_back(std::toupper(c));
369         capitlizeNext = false;
370       }
371       else
372       {
373         ret.push_back(c);
374       }
375     }
376   }
377
378   return ret;
379 }
380
381 void ScriptError( const char* function, v8::Isolate* isolate, std::string errorString )
382 {
383   v8::EscapableHandleScope scope( isolate);
384   std::string errorMsg = std::string(function) + std::string("(), ") + errorString;
385
386   // log out to DALI_LOG_ERROR first, so we know something has gone wrong
387   DALI_LOG_ERROR("%s \n", errorMsg.c_str() );
388
389   // throw a V8 exception, DALi will keep running but we will get a print out
390   // of where the error occured in the JavaScript source
391   isolate->ThrowException( v8::String::NewFromUtf8( isolate, errorMsg.c_str()) );
392 }
393
394 void ScriptWarning( const char* function, std::string warningString )
395 {
396   std::string warningMsg = std::string(function) + std::string("(), ") + warningString;
397   DALI_LOG_WARNING("%s \n", warningMsg.c_str() );
398 }
399
400 bool IsBooleanPrimitiveOrObject( const v8::Local<v8::Value>& value )
401 {
402   return ( value->IsBoolean() || value->IsBooleanObject());
403 }
404
405 bool GetBooleanValue( v8::Isolate* isolate, const v8::Local<v8::Value>& value )
406 {
407   v8::EscapableHandleScope scope( isolate); // may not be required.
408
409   if( value->IsBoolean() )
410   {
411     return value->ToBoolean()->Value();
412   }
413   else if (value->IsBooleanObject() )
414   {
415     const v8::Local<v8::BooleanObject> object = v8::Local<v8::BooleanObject>::Cast(value);
416     return object->BooleanValue();
417   }
418   DALI_SCRIPT_EXCEPTION(isolate, "no bool found");
419   return false;
420 }
421
422 bool IsNumberPrimitiveOrObject( const v8::Local<v8::Value>& value )
423 {
424   return ( value->IsNumber() || value->IsNumberObject());
425 }
426
427 float GetNumberValue( v8::Isolate* isolate, const v8::Local<v8::Value>& value )
428 {
429   v8::EscapableHandleScope scope( isolate); // may not be required.
430
431   if( value->IsNumber() )
432   {
433     return value->ToNumber()->Value();
434   }
435   else if (value->IsNumberObject() )
436   {
437     const v8::Local<v8::NumberObject> object = v8::Local<v8::NumberObject>::Cast(value);
438     return object->ValueOf();
439   }
440
441   DALI_SCRIPT_EXCEPTION(isolate, "no number found?");
442   return 0.f;
443 }
444
445 bool IsStringPrimitiveOrObject( const v8::Local<v8::Value>& value )
446 {
447   return ( value->IsString() || value->IsStringObject());
448 }
449
450 std::string GetStringValue( v8::Isolate* isolate, const v8::Local<v8::Value>& value )
451 {
452   v8::EscapableHandleScope scope( isolate); // may not be required.
453
454   if( value->IsString() )
455   {
456     return V8Utils::v8StringToStdString(value);
457   }
458   else if (value->IsStringObject() )
459   {
460     const v8::Local<v8::StringObject> object = v8::Local<v8::StringObject>::Cast(value);
461     return V8Utils::v8StringToStdString( object->ValueOf() );
462   }
463
464   DALI_SCRIPT_EXCEPTION(isolate, "no string found?");
465   return "";
466 }
467
468
469 Property::Value GetPropertyValueFromObject( bool& found, v8::Isolate* isolate, const   v8::Local<v8::Value >& value  )
470 {
471   v8::HandleScope handleScope( isolate);
472
473   Property::Value  daliPropertyValue;// creates a property with Property::NONE
474
475   found = false;
476
477   if( value->IsObject() )
478   {
479     v8::Local<v8::Object> object = v8::Handle<v8::Object>::Cast( value );
480
481     if( BaseWrappedObject::IsWrappedTypeAPropertyValue( object ) )
482     {
483       found = true;
484       PropertyValueWrapper* propertyWrapper = PropertyValueWrapper::Unwrap( isolate, object );
485       return propertyWrapper->GetValue();
486     }
487     else if( value->IsArray() )
488     {
489       found = true;
490       return PropertyValueWrapper::VectorOrMatrixFromV8Array( isolate, object);//todo check for V8 array / map?
491     }
492   }
493   else if( value->IsBoolean() )
494   {
495     found = true;
496     v8::Local<v8::Boolean> v = value->ToBoolean();
497     return Dali::Property::Value(v->Value());
498   }
499   else if( value->IsNumber() )
500   {
501     found = true;
502     v8::Local<v8::Number> v = value->ToNumber();
503     return Dali::Property::Value(static_cast<float>(v->Value()));
504   }
505   else if( value->IsInt32() || value->IsUint32() )
506   {
507     found = true;
508     v8::Local<v8::Int32> v = value->ToInt32();
509     return Dali::Property::Value(static_cast<int>(v->Value()));
510   }
511   else if( value->IsString() )
512   {
513     found = true;
514     std::string valueString = V8Utils::v8StringToStdString( value );
515     return Dali::Property::Value(valueString);
516   }
517
518   return daliPropertyValue;
519
520 }
521
522 Property::Map GetPropertyMapFromObject( v8::Isolate* isolate, const v8::Local<v8::Object>& object)
523 {
524   v8::Local<v8::Array> properties = object->GetPropertyNames();
525   Property::Map propertyMap;    // empty map
526
527   for(  unsigned int i = 0; i <  properties->Length(); ++i)
528   {
529     // Get the key
530     v8::Local<v8::Value> key = properties->Get( i );
531     std::string keyString = v8StringToStdString( key );
532
533     // Get the value
534     v8::Local<v8::Value> value = object->Get( key );
535
536     if( value->IsBoolean() )
537     {
538       v8::Local<v8::Boolean> v = value->ToBoolean();
539       propertyMap[ keyString ] = v->Value();
540     }
541     else if( value->IsNumber() )
542     {
543       v8::Local<v8::Number> v = value->ToNumber();
544       propertyMap[ keyString ] = static_cast<float>(v->Value());
545     }
546     else if( value->IsInt32() || value->IsUint32() )
547     {
548       v8::Local<v8::Int32> v = value->ToInt32();
549       propertyMap[ keyString ] = static_cast<int>(v->Value());
550     }
551     else if( value->IsString() )
552     {
553       std::string valueString = V8Utils::v8StringToStdString( value );
554       propertyMap[ keyString ] = valueString.c_str();
555     }
556     else if( value->IsArray() )
557     {
558       propertyMap[ keyString ] = PropertyValueWrapper::VectorOrMatrixFromV8Array( isolate, value);
559     }
560     else if( value->IsObject() )
561     {
562       Dali::Property::Map map = V8Utils::GetPropertyMapFromObject(isolate, value->ToObject());
563       if( !map.Empty() )
564       {
565         propertyMap[ keyString ] = Dali::Property::Value( map );
566       }
567     }
568   }
569
570   return propertyMap;
571 }
572
573 Actor GetActorFromObject( v8::Isolate* isolate, bool& found, v8::Local<v8::Object>& object)
574 {
575   v8::HandleScope handleScope( isolate);
576   found = false;
577
578   if( BaseWrappedObject::IsWrappedType ( isolate, object, BaseWrappedObject::ACTOR ))
579   {
580     HandleWrapper* handleWrapper = HandleWrapper::Unwrap( isolate, object );
581     return Actor::DownCast( handleWrapper->mHandle );
582   }
583   return Actor();
584 }
585
586
587 int GetIntegerParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args, int defaultValue  )
588 {
589   found = false;
590   unsigned int length = args.Length();
591   if( index >= length )
592   {
593     return defaultValue;
594   }
595   if( args[ index ]->IsInt32() )
596   {
597     found = true;
598     return args[ index ]->Int32Value();
599   }
600   else
601   {
602     return defaultValue;
603   }
604 }
605
606 float GetFloatParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args, float defaultValue  )
607 {
608   found = false;
609   unsigned int length = args.Length();
610   if( index >= length )
611   {
612     return defaultValue;
613   }
614   if( args[ index ]->IsNumber() )
615   {
616     found = true;
617     return args[ index ]->NumberValue();
618   }
619   else
620   {
621     return defaultValue;
622   }
623 }
624
625 std::string GetStringParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
626 {
627   found = false;
628   unsigned int length = args.Length();
629
630   if( index >= length )
631   {
632     return std::string();
633   }
634   if( args[ index ]->IsString() )
635   {
636     found = true;
637     return v8StringToStdString( args[ index ]);
638   }
639   else
640   {
641     return std::string();
642   }
643 }
644
645 bool GetBooleanParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
646 {
647   v8::HandleScope handleScope( isolate);
648
649   found = false;
650   unsigned int length = args.Length();
651   if( index >= length )
652   {
653     return false;
654   }
655   if( args[ index ]->IsBoolean() )
656   {
657     found = true;
658     v8::Local<v8::Boolean> v = args[ index ]->ToBoolean();
659     return v->Value();
660   }
661   else
662   {
663     return false;
664   }
665 }
666
667 void* GetArrayBufferViewParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args  )
668 {
669   found = false;
670   unsigned int length = args.Length();
671   if( index < length && args[index]->IsArrayBufferView() )
672   {
673     found = true;
674     v8::ArrayBufferView* bufferView = v8::ArrayBufferView::Cast(*(args[index]));
675     v8::Handle<v8::ArrayBuffer> buffer = bufferView->Buffer();
676     v8::ArrayBuffer::Contents contents = buffer->Externalize();
677     return contents.Data();
678   }
679   else
680   {
681     return NULL;
682   }
683 }
684
685 Handle GetHandleParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
686 {
687   v8::HandleScope handleScope( isolate);
688
689   found = false;
690   unsigned int length = args.Length();
691   if( index >= length )
692   {
693     return Handle();
694   }
695
696   if( args[ index ]->IsObject() )
697   {
698     v8::Local<v8::Object> object = args[ index ]->ToObject();
699     v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField(0) );
700     void* ptr = field->Value();
701     if( ptr )
702     {
703         found = true;
704         HandleWrapper* wrapper = static_cast< HandleWrapper *>(ptr);
705         return wrapper->GetHandle();
706     }
707   }
708   return Handle();
709 }
710
711 Vector2 GetVector2Parameter( unsigned int index,  bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
712 {
713   v8::HandleScope handleScope( isolate);
714   unsigned int length =  args.Length();
715   Vector2 ret;
716   found = false;
717
718   if( index < length )
719   {
720     if( args[ index ]->IsObject() )
721     {
722       Dali::Property::Value value;
723       value = PropertyValueWrapper::ExtractPropertyValue( isolate, args[index], Dali::Property::VECTOR2 );
724       if( value.GetType() == Dali::Property::VECTOR2)
725       {
726         found = true;
727         value.Get(ret);
728       }
729       else
730       {
731         DALI_SCRIPT_EXCEPTION(isolate, "Missing Vector2 parameter");
732       }
733     }
734   }
735   else
736   {
737     DALI_SCRIPT_EXCEPTION(isolate, "Missing Vector2 parameter");
738   }
739
740   return ret;
741 }
742
743 Vector2 GetVector2ParameterFrom2Float( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
744 {
745   Vector2 ret(0.0f,0.0f);
746   bool bFound(false);
747   unsigned int argCount( args.Length() );
748
749   if( index+2 >= argCount )
750   {
751     DALI_SCRIPT_EXCEPTION(isolate, "Missing parameter");
752   }
753
754   found = true;
755   ret.x = V8Utils::GetFloatParameter( index, bFound, isolate, args, 0.0f );
756   found = found && bFound;
757   ret.y = V8Utils::GetFloatParameter( index+1, bFound, isolate, args, 0.0f );
758   found = found && bFound;
759
760   return ret;
761 }
762
763 Vector3 GetVector3Parameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args)
764 {
765   v8::HandleScope handleScope( isolate);
766   unsigned int argCount( args.Length() );
767   Vector3 ret;
768   found = false;
769   if( index < argCount )
770   {
771     if( args[ index ]->IsObject() )
772     {
773       Dali::Property::Value value;
774       value = PropertyValueWrapper::ExtractPropertyValue( isolate, args[index], Dali::Property::VECTOR3 );
775       if( value.GetType() == Dali::Property::VECTOR3)
776       {
777         found = true;
778         value.Get(ret);
779       }
780       else
781       {
782         DALI_SCRIPT_EXCEPTION(isolate, "Missing Vector3 parameter");
783       }
784     }
785   }
786   else
787   {
788     DALI_SCRIPT_EXCEPTION(isolate, "Missing Vector3 parameter");
789
790   }
791
792   return ret;
793 }
794
795 Vector4 GetVector4Parameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args)
796 {
797   v8::HandleScope handleScope( isolate);
798   unsigned int argCount( args.Length() );
799   Vector4 ret;
800   found = false;
801
802   if( index < argCount )
803   {
804     if( args[ index ]->IsObject() )
805     {
806       Dali::Property::Value value;
807       value = PropertyValueWrapper::ExtractPropertyValue( isolate, args[index], Dali::Property::VECTOR4 );
808       if( value.GetType() == Dali::Property::VECTOR4)
809       {
810         found = true;
811         value.Get(ret);
812       }
813       else
814       {
815         DALI_SCRIPT_EXCEPTION(isolate, "Missing Vector4 parameter");
816       }
817     }
818   }
819   else
820   {
821     DALI_SCRIPT_EXCEPTION(isolate, "Missing Vector4 parameter");
822   }
823
824   return ret;
825 }
826
827
828 Rect<int> GetRectIntParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
829 {
830   v8::HandleScope handleScope( isolate);
831
832    found = false;
833    int length = args.Length() - index;
834
835    // if it's an array read the 2 numbers into a vector2
836    if( length == 4 )
837    {
838      if( args[ 0 + index ]->IsInt32() &&
839          args[ 1 + index ]->IsInt32() &&
840          args[ 2 + index ]->IsInt32() &&
841          args[ 3 + index ]->IsInt32() )
842      {
843        found = true;
844        Rect<int> rect( args[ 0 + index ]->Int32Value(),
845                        args[ 1 + index ]->Int32Value(),
846                        args[ 2 + index ]->Int32Value(),
847                        args[ 3 + index ]->Int32Value() );
848        return rect;
849      }
850    }
851    // this will extract a Vector4, if it is a Vector4 or a Javascript array object
852    if( args[ index ]->IsObject() )
853    {
854      Dali::Property::Value value;
855      value = PropertyValueWrapper::ExtractPropertyValue( isolate, args[index], Dali::Property::RECTANGLE );
856      if( value.GetType() == Dali::Property::RECTANGLE)
857      {
858        found = true;
859        Rect<int> rect;
860        value.Get(rect);
861        return rect;
862      }
863
864      // @todo support vector4 as well?
865    }
866    return Rect<int>();
867 }
868
869 Actor GetActorParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
870 {
871   BaseWrappedObject* wrapper = GetWrappedDaliObjectParameter( index, BaseWrappedObject::ACTOR, isolate, args);
872   ActorWrapper* actorWrapper = static_cast< ActorWrapper*>( wrapper );
873   if( actorWrapper )
874   {
875     found = true;
876     return actorWrapper->GetActor();
877   }
878   else
879   {
880     return Actor();
881   }
882 }
883
884 Layer GetLayerParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
885 {
886   Actor actor = GetActorParameter( index, found, isolate, args );
887   return Layer::DownCast( actor );
888 }
889
890 Image GetImageParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
891 {
892   BaseWrappedObject* wrappedObject = V8Utils::GetWrappedDaliObjectParameter( index, BaseWrappedObject::IMAGE, isolate, args );
893   if( wrappedObject )
894   {
895     found = true;
896     ImageWrapper* wrapper = static_cast< ImageWrapper *>(wrappedObject);
897     return wrapper->GetImage();
898   }
899   else
900   {
901     return Image();
902   }
903
904 }
905
906 RenderTask GetRenderTaskParameter( unsigned int paramIndex, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
907 {
908   found = false;
909   BaseWrappedObject* wrappedObject = V8Utils::GetWrappedDaliObjectParameter( paramIndex, BaseWrappedObject::RENDER_TASK, isolate, args );
910   if( wrappedObject )
911   {
912     found = true;
913     RenderTaskWrapper* wrapper = static_cast< RenderTaskWrapper *>(wrappedObject);
914     return wrapper->GetRenderTask();
915   }
916   else
917   {
918     return RenderTask(); // empty handle
919   }
920 }
921
922 BaseWrappedObject* GetWrappedDaliObjectParameter( unsigned int index,  BaseWrappedObject::Type type,  v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
923 {
924   v8::HandleScope handleScope( isolate);
925   unsigned int length = args.Length();
926
927   if( index >= length )
928   {
929     return NULL;
930   }
931
932   if( !args[ index ]->IsObject() )
933   {
934     return NULL;
935   }
936
937   v8::Local<v8::Object> object = args[ index ]->ToObject();
938
939   if( BaseWrappedObject::IsWrappedType ( isolate, object, type ))
940   {
941     v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField(0) );
942     void* ptr = field->Value();
943     BaseWrappedObject* wrapper = static_cast< BaseWrappedObject *>(ptr);
944     return wrapper;
945   }
946   return NULL;
947 }
948
949
950 Property::Value GetPropertyValueParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
951 {
952   v8::HandleScope handleScope( isolate);
953
954   Property::Value  daliPropertyValue;// creates a property with Property::INVALID
955
956   found = false;
957   unsigned int length = args.Length();
958
959   if( index >= length )
960   {
961     return daliPropertyValue;
962   }
963   v8::Local<v8::Value > value = args[ index ];
964
965   return GetPropertyValueFromObject( found, isolate, value);
966 }
967
968 Property::Map GetPropertyMapParameter( unsigned int index, bool& found, v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
969 {
970   v8::HandleScope handleScope( isolate);
971
972   Property::Map propertyMap;    // empty map
973
974   found = false;
975   unsigned int length = args.Length();
976
977   if( index >= length )
978   {
979     return propertyMap;
980   }
981
982   if( !args[ index ]->IsObject() )
983   {
984     return propertyMap;
985   }
986   found = true;
987
988   // go through each key value pair
989   v8::Local<v8::Object> obj = args[ index ]->ToObject();
990
991   return GetPropertyMapFromObject( isolate, obj );
992
993 }
994
995 void CreatePropertyMap( v8::Isolate* isolate, const Property::Map& map, v8::Local<v8::Object>& object )
996 {
997   v8::HandleScope handleScope( isolate);
998
999   // we're converting a dali property map in to a JavaScript property map
1000   if( map.Count() == 0 )
1001   {
1002     return;
1003   }
1004
1005   for( unsigned int index = 0; index < map.Count(); ++index )
1006   {
1007     const std::string& key = map.GetKey( index );
1008     Property::Value& value = map.GetValue( index );
1009     v8::Local<v8::Value> v8Value;
1010
1011     switch( value.GetType() )
1012     {
1013       case Dali::Property::FLOAT:
1014       {
1015         v8Value = v8::Number::New( isolate, value.Get<float>()  );
1016         break;
1017       }
1018       case Dali::Property::BOOLEAN:
1019       {
1020         v8Value = v8::Boolean::New(  isolate, value.Get<bool>());
1021         break;
1022       }
1023       case Dali::Property::INTEGER:
1024       {
1025         v8Value = v8::Integer::New( isolate, value.Get<int>());
1026         break;
1027       }
1028       case Dali::Property::STRING:
1029       {
1030         std::string string = value.Get< std::string >();
1031         v8Value = v8::String::NewFromUtf8( isolate,  string.c_str());
1032         break;
1033       }
1034       case Dali::Property::VECTOR2:
1035       {
1036         // create a vector2
1037         Vector2 vec = value.Get<Vector2>();
1038         v8::Local<v8::Array> array= v8::Array::New( isolate, 2 );
1039         array->Set( 0 , v8::Number::New(isolate, vec.x));
1040         array->Set( 1 , v8::Number::New(isolate, vec.y));
1041         v8Value = array;
1042         break;
1043       }
1044       case Dali::Property::VECTOR3:
1045       {
1046         // create a vector 3
1047         Vector3 vec = value.Get<Vector3>();
1048         v8::Local<v8::Array> array= v8::Array::New( isolate, 3 );
1049         array->Set( 0 , v8::Number::New(isolate, vec.x));
1050         array->Set( 1 , v8::Number::New(isolate, vec.y));
1051         array->Set( 2 , v8::Number::New(isolate, vec.z));
1052         v8Value = array;
1053         break;
1054       }
1055       case Dali::Property::VECTOR4:
1056       {
1057         // create a vector 4
1058         Vector4 vec = value.Get<Vector4>();
1059         v8::Local<v8::Array> array= v8::Array::New( isolate, 4 );
1060         array->Set( 0 , v8::Number::New(isolate, vec.x));
1061         array->Set( 1 , v8::Number::New(isolate, vec.y));
1062         array->Set( 2 , v8::Number::New(isolate, vec.z));
1063         array->Set( 3 , v8::Number::New(isolate, vec.w));
1064         v8Value = array;
1065         break;
1066       }
1067
1068       default:
1069       {
1070         DALI_SCRIPT_EXCEPTION( isolate, "Primitive mismatch \n");
1071         return;
1072       }
1073     }
1074     object->Set( v8::String::NewFromUtf8( isolate, key.c_str() ), v8Value );
1075   }
1076 }
1077
1078 void ReadFloatArguments( bool& foundAllArguments, float* data, unsigned int dataSize, const v8::FunctionCallbackInfo< v8::Value >& args, float defaultValue )
1079 {
1080   foundAllArguments = true;
1081   unsigned int length = args.Length();
1082
1083   if( length < dataSize )
1084   {
1085     foundAllArguments = false;
1086   }
1087
1088   for( unsigned int i = 0; i< dataSize ;i++ )
1089   {
1090     if( i < length )
1091     {
1092       if( args[ i ]->IsNumber()  )
1093       {
1094         data[i] = args[i]->NumberValue();
1095       }
1096       else
1097       {
1098         data[i] = defaultValue;
1099         foundAllArguments = false;   // bad argument
1100       }
1101     }
1102     else
1103     {
1104       data[i] = defaultValue; // not enough arguments
1105     }
1106   }
1107
1108 }
1109
1110 void ReadIntegerArguments( bool& foundAllArguments, int* data, int dataSize, const v8::FunctionCallbackInfo< v8::Value >& args, int defaultValue )
1111 {
1112   foundAllArguments = true;
1113   int length = args.Length();
1114   if( length < dataSize )
1115   {
1116     foundAllArguments = false;
1117   }
1118
1119   for( int i = 0; i< dataSize ;i++ )
1120   {
1121     if( i < length )
1122     {
1123       if( args[ i ]->IsInt32()  )
1124       {
1125         data[i] = args[i]->Int32Value();
1126       }
1127       else
1128       {
1129         data[i] = defaultValue;
1130         foundAllArguments = false;   // bad argument
1131       }
1132     }
1133     else
1134     {
1135       data[i] = defaultValue; // not enough arguments
1136     }
1137   }
1138
1139 }
1140 } // namespace V8Utils
1141
1142 } // namespace V8Plugin
1143
1144 } // namespace Dali