Sirikata
|
00001 #ifndef __SIRIKATA_JS_CONTEXT_STRUCT_HPP__ 00002 #define __SIRIKATA_JS_CONTEXT_STRUCT_HPP__ 00003 00004 #include <sirikata/oh/HostedObject.hpp> 00005 #include <v8.h> 00006 #include <vector> 00007 #include "../JSSystemNames.hpp" 00008 #include "../JSObjects/JSFields.hpp" 00009 #include "JSSuspendable.hpp" 00010 #include "../JSEntityCreateInfo.hpp" 00011 #include "../JSUtil.hpp" 00012 #include <sirikata/core/util/Vector3.hpp> 00013 #include <sirikata/oh/Storage.hpp> 00014 #include <sirikata/core/util/Liveness.hpp> 00015 #include "../EmersonHttpManager.hpp" 00016 #include "../JSVisibleManager.hpp" 00017 #include "JSCapabilitiesConsts.hpp" 00018 #include "../JSCtx.hpp" 00019 00020 namespace Sirikata { 00021 namespace JS { 00022 00023 00024 //need to forward-declare this so that can reference this inside 00025 class JSObjectScript; 00026 class EmersonScript; 00027 class JSPresenceStruct; 00028 class JSTimerStruct; 00029 class JSUtilStruct; 00030 class JSPositionListener; 00031 class JSSystemStruct; 00032 struct PresStructRestoreParams; 00033 00034 struct JSContextStruct : public JSSuspendable, public Liveness 00035 { 00036 JSContextStruct(JSObjectScript* parent, JSPresenceStruct* whichPresence, 00037 SpaceObjectReference home,Capabilities::CapNum capNum, 00038 v8::Handle<v8::ObjectTemplate> contGlobTempl, uint32 contextID, 00039 JSContextStruct* parentContext, JSCtx* jsctx); 00040 00041 ~JSContextStruct(); 00042 00043 //looks in current context and returns the current context as pointer to 00044 //user. if unsuccessful, return null. 00045 static JSContextStruct* decodeContextStruct(v8::Handle<v8::Value> toDecode, String& errorMsg); 00046 00047 uint32 getContextID(); 00048 00049 00050 //contexts can be suspended (suspends all suspendables within the context) 00051 //resumed (takes all suspendables in context and calls resume on them) 00052 //or cleared (marks all objects native to this context and its chilren as 00053 //ready for garbage collection) (also clears all suspendables in the context). 00054 virtual v8::Handle<v8::Value> suspend(); 00055 virtual v8::Handle<v8::Value> resume(); 00056 00057 //clear requests the jsobjectscript to begin to clear the context. 00058 //JSObjectScript calls finishClear, where all other suspendables are cleared 00059 //and the internal state of this object is removed. 00060 virtual v8::Handle<v8::Value> clear(); 00061 void finishClear(); 00062 00063 v8::Handle<v8::Value> struct_suspendContext(); 00064 v8::Handle<v8::Value> struct_resumeContext(); 00065 00066 v8::Handle<v8::Value> checkHeadless(); 00067 00068 //returns an object that contains the system/system object associated with 00069 //this context 00070 v8::Handle<v8::Object> struct_getSystem(); 00071 00072 v8::Handle<v8::Value> struct_create_vis(const SpaceObjectReference& sporefWathcing, JSVisibleDataPtr addParams); 00073 00074 v8::Handle<v8::Value> killEntity(); 00075 00094 void proximateEvent(const SpaceObjectReference& goneFrom, 00095 JSVisibleStruct* jsvis,bool isGone); 00096 00097 00098 v8::Handle<v8::Value> pushEvalContextScopeDirectory(const String& newDir); 00099 v8::Handle<v8::Value> popEvalContextScopeDirectory(); 00100 00101 v8::Handle<v8::Value> storageBeginTransaction(); 00102 v8::Handle<v8::Value> storageCommit(v8::Handle<v8::Function> cb); 00103 v8::Handle<v8::Value> storageWrite(const OH::Storage::Key& key, const String& toWrite, v8::Handle<v8::Function> cb); 00104 v8::Handle<v8::Value> storageRead(const OH::Storage::Key& key, v8::Handle<v8::Function> cb); 00105 v8::Handle<v8::Value> storageErase(const OH::Storage::Key& key, v8::Handle<v8::Function> cb); 00106 v8::Handle<v8::Value> storageRangeRead(const OH::Storage::Key& start, const OH::Storage::Key& finish, v8::Handle<v8::Function> cb); 00107 v8::Handle<v8::Value> storageRangeErase(const OH::Storage::Key& start, const OH::Storage::Key& finish, v8::Handle<v8::Function> cb); 00108 v8::Handle<v8::Value> storageCount(const OH::Storage::Key& start, const OH::Storage::Key& finish, v8::Handle<v8::Function> cb); 00109 00117 v8::Handle<v8::Value> sendSandbox(const String& msgToSend, JSContextStruct* destination); 00118 00119 00120 v8::Handle<v8::Value> setRestoreScript(const String& key, v8::Handle<v8::Function> cb); 00121 00122 00123 v8::Handle<v8::Value> struct_evalInGlobal(const String& native_contents, ScriptOrigin* sOrigin); 00124 00125 00126 //create presence in the place, and with the script specified in eci 00127 v8::Handle<v8::Value> struct_createEntity(EntityCreateInfo& eci); 00128 00129 v8::Handle<v8::Value> struct_setReset(const std::map<SpaceObjectReference, std::vector<SpaceObjectReference> > & proxResSet); 00130 v8::Handle<v8::Value> struct_setScript(const String& script); 00131 v8::Handle<v8::Value> struct_getScript(); 00132 v8::Handle<v8::Value> debug_fileWrite(String& strToWrite,String& filename); 00133 v8::Handle<v8::Value> debug_fileRead(String& filename); 00134 00135 00136 v8::Handle<v8::Value> deserialize(const String& toDeserialize); 00137 00138 v8::Handle<v8::Value> struct_rootReset(); 00139 00140 v8::Handle<v8::Value> restorePresence(PresStructRestoreParams& psrp); 00141 00142 //when add a handler, timer, when inside of context, want to register them. 00143 //That way, when call suspend on context and resume on context, can 00144 //suspend/resume them. 00145 void struct_registerSuspendable (JSSuspendable* toRegister); 00146 void struct_deregisterSuspendable (JSSuspendable* toDeregister); 00147 00148 //if calling deregister through a post. 00149 void struct_asyncDeregisterSuspendable ( 00150 JSSuspendable* toDeregister,Liveness::Token contAlive, 00151 Liveness::Token suspAlive); 00152 00153 //creates a vec3 emerson object out of the vec3d cpp object passed in. 00154 v8::Handle<v8::Value> struct_createVec3(Vector3d& toCreate); 00155 v8::Handle<v8::Value> struct_createQuaternion(Quaternion& toCreate); 00156 00157 //if receiver is one of my presences, or it is the system presence that I 00158 //was created from return true. Otherwise, return false. 00159 bool canReceiveMessagesFor(const SpaceObjectReference& receiver); 00160 00161 00162 00163 void jsscript_print(const String& msg); 00164 void presenceDied(); 00165 00166 v8::Handle<v8::Value> struct_executeScript(v8::Handle<v8::Function> funcToCall,const v8::Arguments& args); 00167 v8::Handle<v8::Value> struct_getAssociatedPresPosition(); 00168 v8::Handle<v8::Value> struct_sendHome(const String& toSend); 00169 //string argument is the filename that we're trying to open and execute 00170 //contents of. 00171 v8::Handle<v8::Value> struct_import(const String& toImportFrom,bool isJS); 00172 //string argument is the filename that we're trying to open and execute 00173 //contents of. 00174 v8::Handle<v8::Value> struct_require(const String& toRequireFrom,bool isJS); 00175 00181 void receiveSandboxMessage(v8::Local<v8::Object> msgObj, JSContextStruct* sender); 00182 00183 00196 v8::Handle<v8::Value> struct_createContext(JSPresenceStruct* jspres,const SpaceObjectReference& canSendTo,Capabilities::CapNum capNum); 00197 00198 // Trigger an event handler 00199 v8::Handle<v8::Value> struct_event(v8::Persistent<v8::Function>& cb); 00200 00201 //create a timer that will fire cb in dur seconds from now, 00202 v8::Handle<v8::Value> struct_createTimeout(double period, v8::Persistent<v8::Function>& cb); 00203 v8::Handle<v8::Value> struct_createTimeout(double period,v8::Persistent<v8::Function>& cb, uint32 contID,double timeRemaining, bool isSuspended, bool isCleared); 00204 00205 00206 v8::Handle<v8::Value> sendMessageNoErrorHandler(JSPresenceStruct* jspres,const String& serialized_message,JSPositionListener* jspl,bool reliable); 00207 00208 00209 //register cb_persist as the default handler that gets thrown 00210 v8::Handle<v8::Value> struct_registerOnPresenceDisconnectedHandler(v8::Persistent<v8::Function> cb_persist); 00211 v8::Handle<v8::Value> struct_registerOnPresenceConnectedHandler(v8::Persistent<v8::Function> cb_persist); 00212 void checkContextConnectCallback(JSPresenceStruct* jspres); 00213 void checkContextDisconnectCallback(JSPresenceStruct* jspres); 00214 00215 00216 00217 //********data 00218 JSObjectScript* jsObjScript; 00219 00220 //this is the context that any and all objects will be run in. 00221 v8::Persistent<v8::Context> mContext; 00222 JSCtx* mCtx; 00223 00224 String getScript(); 00225 //sets proxAddedFunc and proxRemovedFunc, respectively 00226 v8::Handle<v8::Value> proxAddedHandlerCallallback(v8::Handle<v8::Function>cb); 00227 v8::Handle<v8::Value> proxRemovedHandlerCallallback(v8::Handle<v8::Function>cb); 00228 00229 00230 v8::Handle<v8::Value> getAssociatedPresence(); 00231 00232 JSPresenceStruct* getAssociatedPresenceStruct() 00233 { 00234 return associatedPresence; 00235 } 00236 00237 v8::Persistent<v8::Function>proxAddedFunc; 00238 v8::Persistent<v8::Function>proxRemovedFunc; 00239 00240 00247 void httpFail(v8::Persistent<v8::Function> cb,const String& failureReason ); 00254 void httpSuccess(v8::Persistent<v8::Function> cb,EmersonHttpManager::HttpRespPtr httpResp); 00255 v8::Handle<v8::Value> httpRequest(Sirikata::Network::Address addr, Transfer::HttpManager::HTTP_METHOD method, String request, v8::Persistent<v8::Function> cb); 00256 00257 00258 v8::Handle<v8::Value> setSandboxMessageCallback(v8::Persistent<v8::Function> callback); 00259 v8::Handle<v8::Value> setPresenceMessageCallback(v8::Persistent<v8::Function> callback); 00260 00261 v8::Handle<v8::Value> emersonCompileString(const String& toCompile); 00262 00263 //Each entity consists of a sandbox tree. mParentContext points to the 00264 //parent of the current sandbox. (Can be null for root sandbox.) Can 00265 //access children sandboxes through associatedSuspendables map. 00266 JSContextStruct* mParentContext; 00267 00268 //Should always check if empty before using. Contains function to dispatch 00269 //if we ever receive a sandbox message. Takes two arguments: 1: decoded 00270 //sandbox message (should just be an object); 2: sandbox object for sender 00271 //of message; if parent sent message, then the second field is null (which 00272 //should agree with sandbox.PARENT set in std/shim/sandbox.em 00273 v8::Persistent<v8::Function> sandboxMessageCallback; 00274 v8::Persistent<v8::Function> presenceMessageCallback; 00275 00276 //returns associated capabilities number 00277 Capabilities::CapNum getCapNum(); 00278 00279 00280 private: 00281 00282 uint32 mContextID; 00283 00284 //runs through suspendable map to check if have a presence in this sandbox 00285 //matching sporef 00286 bool hasPresence(const SpaceObjectReference& sporef); 00287 00288 //performs the initialization and population of util object, system object, 00289 //and system object's presences array. 00290 void createContextObjects(String* scriptToEval=NULL); 00291 00292 //a function to call within this context for when a presence that was 00293 //created from within this context gets connected. 00294 bool hasOnConnectedCallback; 00295 v8::Persistent<v8::Function> cbOnConnected; 00296 bool hasOnDisconnectedCallback; 00297 v8::Persistent<v8::Function> cbOnDisconnected; 00298 00299 //script associated with this context. 00300 String mScript; 00301 00302 //a pointer to the local presence that is associated with this context. for 00303 //instance, when you call getPosition on the system object, you actually 00304 //end up returning the position of this presence. you send messages from 00305 //this presence, etc. Can be null. 00306 JSPresenceStruct* associatedPresence; 00307 00308 //homeObject is the spaceobjectreference of an object that you can always 00309 //send messages to regardless of permissions 00310 SpaceObjectReference mHomeObject; 00311 00312 //a pointer to the system struct that will be used as a system-like object 00313 //inside of the context. 00314 JSSystemStruct* mSystem; 00315 //mSystem in a v8 wrapper. also, its persistent! 00316 v8::Persistent<v8::Object> systemObj; 00317 00318 v8::Handle<v8::ObjectTemplate> mContGlobTempl; 00319 00320 //struct associated with the Emerson util object that is associated with this 00321 //context. 00322 JSUtilStruct* mUtil; 00323 00324 //flag that is true if in the midst of a clear command. False otherwise 00325 //(prevents messing up iterators in suspendable map). 00326 bool inClear; 00327 00328 //all associated objects that will need to be suspended/resumed if context 00329 //is suspended/resumed 00330 SuspendableMap associatedSuspendables; 00331 00332 //If mInSuspendableLoop is true, doesn't actually delete any suspendable 00333 //objects. Just cues them to be deleted after we end suspendable loop. 00334 bool mInSuspendableLoop; 00335 SuspendableVec suspendablesToDelete; 00336 SuspendableVec suspendablesToAdd; 00337 00338 void flushQueuedSuspendablesToChange(); 00339 00340 00341 //working with presence wrappers: check if associatedPresence is null and throw 00342 //exception if is. 00343 #define NullPresenceCheck(funcName) \ 00344 String fname (funcName); \ 00345 if (associatedPresence == NULL) \ 00346 { \ 00347 String errorMessage = "Error in " + fname + \ 00348 " of JSContextStruct. " + \ 00349 "Have no default presence to perform action with."; \ 00350 \ 00351 return v8::ThrowException( v8::Exception::Error( \ 00352 v8::String::New(errorMessage.c_str()))); \ 00353 } 00354 00355 #define CHECK_EMERSON_SCRIPT_ERROR(emerScriptName,errorIn,whatToCast) \ 00356 EmersonScript* emerScriptName = \ 00357 dynamic_cast<EmersonScript*> (whatToCast); \ 00358 if (emerScriptName == NULL) \ 00359 { \ 00360 return v8::ThrowException( \ 00361 v8::Exception::Error(v8::String::New( \ 00362 "Error. Must not be in headless mode to run " \ 00363 #errorIn \ 00364 ))); \ 00365 } 00366 00367 00368 #define CHECK_EMERSON_SCRIPT_RETURN(emerScriptName,errorIn,whatToCast) \ 00369 EmersonScript* emerScriptName = \ 00370 dynamic_cast<EmersonScript*> (whatToCast); \ 00371 if (emerScriptName == NULL) \ 00372 { \ 00373 JSLOG(error,"Error in " #errorIn ". " << \ 00374 "Must not be in headless mode to run " #errorIn ); \ 00375 \ 00376 return; \ 00377 } 00378 00379 00380 00381 00382 }; //end class 00383 00384 00385 #define INLINE_CONTEXT_CONV_ERROR(toConvert,whereError,whichArg,whereWriteTo) \ 00386 JSContextStruct* whereWriteTo; \ 00387 { \ 00388 String _errMsg = "In " #whereError "cannot convert " #whichArg " to sandbox struct"; \ 00389 whereWriteTo = JSContextStruct::decodeContextStruct(toConvert,_errMsg); \ 00390 if (whereWriteTo == NULL) \ 00391 V8_EXCEPTION_STRING(_errMsg); \ 00392 } 00393 00394 00395 00396 typedef std::vector<JSContextStruct*> ContextVector; 00397 typedef ContextVector::iterator ContextVecIter; 00398 00399 00400 00401 }//end namespace js 00402 }//end namespace sirikata 00403 00404 #endif