Merge "JavaScript support for DALi" into tizen
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / object / handle-wrapper.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 // CLASS HEADER
19 #include "handle-wrapper.h"
20
21 // EXTERNAL INCLUDES
22 #include <sstream>
23
24 // INTERNAL INCLUDES
25 #include <v8-utils.h>
26 #include <shared/base-wrapped-object.h>
27 #include <shared/object-template-helper.h>
28 #include <object/property-value-wrapper.h>
29
30 namespace Dali
31 {
32
33 namespace V8Plugin
34 {
35
36 HandleWrapper::HandleWrapper( BaseWrappedObject::Type type,
37     Handle handle,
38     GarbageCollectorInterface& gc ) :
39  BaseWrappedObject( type, gc ),
40  mHandle( handle )
41 {
42 }
43
44 HandleWrapper::~HandleWrapper()
45 {
46
47 }
48 HandleWrapper*  HandleWrapper::Unwrap( v8::Isolate* isolate, v8::Handle< v8::Object> obj)
49 {
50   v8::HandleScope handleScope( isolate );
51
52   v8::Local<v8::External> field = v8::Local<v8::External>::Cast( obj->GetInternalField(0) );
53   void* ptr = field->Value();
54   return static_cast< HandleWrapper *>(ptr);
55 }
56
57 // may have to do this IsUpper to intercept function calls or as function?
58 void HandleWrapper::PropertyGet( v8::Local<v8::String> propertyName,
59                                         const v8::PropertyCallbackInfo<v8::Value>& info)
60 {
61   v8::Isolate* isolate = info.GetIsolate();
62   v8::HandleScope handleScope( isolate );
63
64   // get the property name
65   std::string name = V8Utils::v8StringToStdString( propertyName );
66
67   if( std::isupper( name[0] ))
68   {
69     return;
70   }
71
72   // unwrap the object
73   HandleWrapper* handleWrapper = Unwrap( isolate, info.This() );
74   Handle handle =  handleWrapper->mHandle;
75
76   // get the property index
77   // convert from camel case to dali property style with hyphens
78   std::string daliPropertyName = V8Utils::JavaScriptNameToPropertyName(name);
79   Dali::Property::Index index = handle.GetPropertyIndex( daliPropertyName );
80
81   if(index != Dali::Property::INVALID_INDEX)
82   {
83     Dali::Property::Value value = handle.GetProperty(index);
84
85     // Simple Dali properties (ints, strings, bools etc) are stored as JavaScript primitives (v8::Boolean ...)
86     // more complex properties (Vectors, Rectangles...) are wrapped by a JavaScript object
87     v8::Local<v8::Object> ret = PropertyValueWrapper::WrapDaliProperty( isolate, value );
88
89     info.GetReturnValue().Set( ret );
90   }
91   else
92   {
93     //  std::string error="Invalid property Get for "+name + "\n";
94     // DALI_SCRIPT_EXCEPTION( isolate, error );
95   }
96
97 }
98 void HandleWrapper::PropertySet( v8::Local<v8::String> propertyName,
99                   v8::Local<v8::Value> javaScriptValue,
100                   const v8::PropertyCallbackInfo<v8::Value>& info)
101 {
102
103   v8::Isolate* isolate = info.GetIsolate();
104   v8::HandleScope handleScope( isolate );
105
106   // get the property name
107   std::string name = V8Utils::v8StringToStdString( propertyName );
108
109   // try to filter out function calls before going to the property system
110   // @todo use installed functions to generate a map
111   if( ( name.compare(0,2,"is") == 0 )  ||
112       ( name.compare(0,3,"get") == 0 ) ||
113       ( name.compare(0,3,"add") == 0 ) ||
114       ( name.compare(0,3,"set") == 0 ) ||
115       ( name.compare(0,3,"get") == 0 ) ||
116       ( name.compare(0,4,"find") == 0 ) ||
117       ( name.compare(0,6,"remove") == 0 )
118      )
119   {
120     //
121     return;
122   }
123   // unwrap the object
124   HandleWrapper* handleWrapper = Unwrap( isolate, info.This() );
125   if( !handleWrapper )
126   {
127     // printf("setting property name %s \n", name.c_str());
128     return;
129   }
130
131  // DALI_ASSERT_DEBUG( handleWrapper && "not a dali object");
132   Handle handle =  handleWrapper->mHandle;
133
134   // convert from camel case to dali property style with hyphens
135   std::string daliPropertyName = V8Utils::JavaScriptNameToPropertyName(name);
136   Dali::Property::Index index = handle.GetPropertyIndex( daliPropertyName );
137
138   if(index != Dali::Property::INVALID_INDEX)
139   {
140     Dali::Property::Type type = handle.GetPropertyType(index);
141
142     // we know the type we want to set ( int, vector, etc..)
143     // try and convert the javascript value in to the type we want.
144     Dali::Property::Value value = PropertyValueWrapper::ExtractPropertyValue( isolate, javaScriptValue, type);
145
146     if( Dali::Property::NONE == value.GetType() )
147       {
148         std::stringstream msg;
149         msg << "Invalid property Set: '";
150         msg << name;
151         msg << "(Index = ";
152         msg << index;
153         msg << ")";
154         msg << "' Cannot convert value to correct type: (";
155         msg << type;
156         msg << ")";
157         msg << Dali::PropertyTypes::GetName(type);
158         DALI_SCRIPT_EXCEPTION( isolate, msg.str().c_str());
159       }
160       else
161       {
162         handle.SetProperty( index, value );
163       }
164   }
165   else
166   {
167     std::string error="Invalid property Set for "+name + "\n";
168     DALI_SCRIPT_EXCEPTION( isolate, error );
169   }
170 }
171
172 void HandleWrapper::AddInterceptsToTemplate( v8::Isolate* isolate, v8::Local<v8::ObjectTemplate>& objTemplate )
173 {
174   v8::HandleScope handleScope( isolate );
175
176   objTemplate->SetNamedPropertyHandler( HandleWrapper::PropertyGet, HandleWrapper::PropertySet);
177
178   ObjectTemplateHelper::AddSignalConnectAndDisconnect( isolate, objTemplate );
179
180 }
181
182
183 } // namespace V8Plugin
184
185 } // namespace Dali