2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "dali-wrapper.h"
23 #include <object/property-value-wrapper.h>
24 #include <dali/integration-api/debug.h>
25 #include <actors/actor-wrapper.h>
26 #include <stage/stage-wrapper.h>
27 #include <image/image-wrapper.h>
28 #include <animation/linear-constrainer-wrapper.h>
29 #include <animation/path-constrainer-wrapper.h>
30 #include <animation/path-wrapper.h>
31 #include <animation/animation-wrapper.h>
32 #include <events/pan-gesture-detector-wrapper.h>
33 #include <shader-effects/shader-effect-wrapper.h>
34 #include <object/property-buffer-wrapper.h>
35 #include <rendering/geometry-wrapper.h>
36 #include <rendering/material-wrapper.h>
37 #include <rendering/renderer-wrapper.h>
38 #include <rendering/shader-wrapper.h>
39 #include <rendering/sampler-wrapper.h>
40 #include <shared/object-template-helper.h>
41 #include <constants/constants-wrapper.h>
42 #include <toolkit/builder/builder-wrapper.h>
43 #include <toolkit/focus-manager/keyboard-focus-manager-wrapper.h>
55 * This string defines how the global DALi object/namespace is used from JavaScript
56 * E.g. new dali.Image or dali.stage.add( )
58 const char* const DALI_API_NAME = "dali";
61 * lookup table for setting up function calls for creating Dali objects
62 * e.g. new dali.TextActor()
64 const ApiFunction ConstructorFunctionTable[]=
66 { "Rotation", PropertyValueWrapper::NewRotation},
67 { "Matrix", PropertyValueWrapper::NewMatrix},
68 { "Path", PathWrapper::NewPath },
69 { "PathConstrainer", PathConstrainerWrapper::NewPathConstrainer},
70 { "LinearConstrainer", LinearConstrainerWrapper::NewLinearConstrainer},
71 { "Actor", ActorWrapper::NewActor },
72 { "ImageActor", ActorWrapper::NewActor },
73 { "CameraActor", ActorWrapper::NewActor },
74 { "Layer", ActorWrapper::NewActor },
75 { "Control", ActorWrapper::NewControl },
76 { "ResourceImage", ImageWrapper::NewImage },
77 { "BufferImage", ImageWrapper::NewImage },
78 { "NinePatchImage", ImageWrapper::NewImage },
79 { "FrameBufferImage", ImageWrapper::NewImage },
80 { "Animation", AnimationWrapper::NewAnimation},
81 { "ShaderEffect", ShaderEffectWrapper::NewShaderEffect},
82 { "Shader", ShaderWrapper::NewShader},
83 { "Sampler", SamplerWrapper::NewSampler},
84 { "Material", MaterialWrapper::NewMaterial},
85 { "Geometry", GeometryWrapper::NewGeometry},
86 { "Renderer", RendererWrapper::NewRenderer},
87 { "PropertyBuffer", PropertyBufferWrapper::NewPropertyBuffer},
88 { "Builder", BuilderWrapper::NewBuilder},
89 { "PanGestureDetector", PanGestureDetectorWrapper::NewPanGestureDetector},
93 const unsigned int PropertyFunctionTableCount = sizeof(ConstructorFunctionTable)/sizeof(ConstructorFunctionTable[0]);
95 void FatalErrorCallback(const char* location, const char* message)
97 DALI_LOG_ERROR("%s, %s \n",location,message);
98 DALI_ASSERT_ALWAYS( 0 && "V8 fatal error");
101 #if defined(DEBUG_ENABLED)
102 // default to verbose logging
103 Integration::Log::Filter* gLogExecuteFilter( Integration::Log::Filter::New(Debug::Verbose, false, "EXECUTE_JAVASCRIPT") );
105 } // un-named name space
109 bool DaliWrapper::mInstanceCreated = false;
110 DaliWrapper* DaliWrapper::mWrapper = NULL;
112 DaliWrapper::DaliWrapper( RunMode runMode, v8::Isolate* isolate )
113 :mIsolate( isolate ),
118 DaliWrapper::~DaliWrapper()
120 mInstanceCreated = false;
123 DaliWrapper& DaliWrapper::Get()
125 if( !mInstanceCreated )
127 mWrapper = new DaliWrapper( RUNNING_STANDALONE, NULL );
129 mInstanceCreated = true;
131 mWrapper->InitializeStandAlone();
137 v8::Local<v8::Object> DaliWrapper::CreateWrapperForNodeJS( v8::Isolate* isolate )
139 v8::EscapableHandleScope handleScope( isolate);
141 mInstanceCreated = true;
143 mWrapper = new DaliWrapper( RUNNING_IN_NODE_JS, isolate );
145 v8::Local<v8::Object> dali = mWrapper->CreateDaliObject();
147 // As we running inside node, we already have an isolate and context
148 return handleScope.Escape( dali );
151 v8::Local<v8::Object> DaliWrapper::CreateDaliObject()
153 v8::EscapableHandleScope handleScope( mIsolate );
155 // Create dali object used for creating objects, and accessing constant values
156 // e.g. var x = new dali.Actor(), or var col = dali.COLOR_RED;
158 v8::Local<v8::ObjectTemplate> daliObjectTemplate = NewDaliObjectTemplate( mIsolate );
161 v8::Local<v8::Object> stageObject = StageWrapper::WrapStage( mIsolate, Stage::GetCurrent() );
162 daliObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "stage") , stageObject );
164 v8::Local<v8::Object> keyboardObject = KeyboardFocusManagerWrapper::WrapKeyboardFocusManager( mIsolate,Toolkit::KeyboardFocusManager::Get() );
165 daliObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "keyboardFocusManager") , keyboardObject );
168 //create an instance of the template
169 v8::Local<v8::Object> daliObject = daliObjectTemplate->NewInstance();
171 ConstantsWrapper::AddDaliConstants( mIsolate, daliObject);
173 daliObject->Set( v8::String::NewFromUtf8( mIsolate, "V8_VERSION") ,v8::String::NewFromUtf8( mIsolate, v8::V8::GetVersion() ));
175 return handleScope.Escape( daliObject );
179 void DaliWrapper::SetFlagsFromString(const std::string &flags)
181 v8::V8::SetFlagsFromString(flags.c_str(), flags.size());
184 void DaliWrapper::Shutdown()
186 // if we're running inside node then we don't have ownership of the context
187 if( mRunMode == RUNNING_IN_NODE_JS )
192 DALI_LOG_WARNING("Destroying V8 DALi context\n");
194 if( !mContext.IsEmpty())
196 v8::HandleScope handleScope( mIsolate );
197 v8::Local<v8::Context> context = v8::Local<v8::Context>::New(mIsolate, mContext);
198 context->Exit(); // exit the context
199 mContext.Reset(); // destroys the context
203 bool DaliWrapper::ExecuteBuffer(const std::string &sourceCode, const std::string &sourceFileName)
205 return mModuleLoader.ExecuteScript( mIsolate, sourceCode, sourceFileName );
208 bool DaliWrapper::ExecuteFile( const std::string& sourceFileName )
210 DALI_LOG_INFO( gLogExecuteFilter, Debug::Verbose, "Executing source file %s \n",sourceFileName.c_str() );
212 return mModuleLoader.ExecuteScriptFromFile( mIsolate, sourceFileName );
215 GarbageCollectorInterface& DaliWrapper::GetDaliGarbageCollector()
217 return mGarbageCollector;
220 void DaliWrapper::ApplyGlobalObjectsToContext( v8::Local<v8::Context> context )
222 v8::HandleScope handleScope( mIsolate );
224 // Add global objects ( functions/ values ) e.g. log function
225 // create a console.log and console.error functions
226 v8::Local<v8::ObjectTemplate> consoleObjectTemplate = v8::ObjectTemplate::New( mIsolate );
227 consoleObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "log"), v8::FunctionTemplate::New( mIsolate, V8Utils::Log));
228 consoleObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "error"), v8::FunctionTemplate::New( mIsolate, V8Utils::LogError));
230 context->Global()->Set( v8::String::NewFromUtf8( mIsolate, "console"), consoleObjectTemplate->NewInstance() );
232 // add require functionality
233 context->Global()->Set( v8::String::NewFromUtf8( mIsolate, "require"), v8::FunctionTemplate::New( mIsolate, DaliWrapper::Require)->GetFunction());
235 // Create the Dali object
236 // @todo consider forcing developers to perform require('dali') if we want to avoid polluting the global namespace
237 v8::Local<v8::Object> daliObject = CreateDaliObject();
239 // allow developers to require('dali'); // this is to maintain compatibility with node.js where dali is not part of the global namespace
240 mModuleLoader.StorePreBuiltModule( mIsolate, daliObject, DALI_API_NAME );
242 context->Global()->Set( v8::String::NewFromUtf8( mIsolate, DALI_API_NAME),daliObject );
246 void DaliWrapper::InitializeStandAlone()
250 v8::V8::InitializeICU();
252 v8::V8::Initialize();
254 // default isolate removed from V8 version 3.27.1 and beyond.
255 mIsolate = v8::Isolate::New();
259 v8::V8::SetFatalErrorHandler( FatalErrorCallback );
262 // if context is null, create it and add dali object to the global object.
263 if( mContext.IsEmpty())
265 v8::HandleScope handleScope( mIsolate );
267 // create a new context.
268 // Isolate = isolated copy of the V8 including a heap manager, a garbage collector
269 // Only 1 thread can access a single Isolate at a given time. However, multiple Isolates can be run in parallel.
270 // Context = multiple contexts can exist in a given Isolate, and share data between contexts
271 v8::Local<v8::Context> context = v8::Context::New( mIsolate );
275 // Apply global objects like dali and console to the context
276 ApplyGlobalObjectsToContext(context);
278 mContext.Reset( mIsolate, context);
281 DALI_LOG_INFO( gLogExecuteFilter, Debug::Verbose, "V8 Library %s loaded \n", v8::V8::GetVersion() );
285 v8::Handle<v8::ObjectTemplate> DaliWrapper::NewDaliObjectTemplate( v8::Isolate* isolate )
287 v8::EscapableHandleScope handleScope( isolate );
289 // create the template
290 v8::Local< v8::ObjectTemplate > objTemplate = v8::ObjectTemplate::New( isolate );
292 // Add some value properties ( a property can be a primitive value, an object or a function).
293 objTemplate->Set( v8::String::NewFromUtf8( isolate, "BUILD"),
294 v8::String::NewFromUtf8( isolate, "Dali binary built on:" __DATE__ ", at " __TIME__));
296 #ifdef DALI_DATA_READ_ONLY_DIR
297 // add the data data directory,
298 objTemplate->Set( v8::String::NewFromUtf8( isolate, "DALI_DATA_DIRECTORY"),
299 v8::String::NewFromUtf8( isolate, DALI_DATA_READ_ONLY_DIR));
301 // add our constructor functions
302 ObjectTemplateHelper::InstallFunctions( isolate,
304 ConstructorFunctionTable,
305 PropertyFunctionTableCount,
306 ObjectTemplateHelper::CONSTRUCTOR_FUNCTIONS);
308 return handleScope.Escape( objTemplate );
311 void DaliWrapper::Require(const v8::FunctionCallbackInfo< v8::Value >& args)
313 DaliWrapper& wrapper( DaliWrapper::Get() );
314 wrapper.mModuleLoader.Require( args );
318 } // namespace V8Plugin