Sirikata
liboh/plugins/js/JSObjectStructs/JSContextStruct.hpp
Go to the documentation of this file.
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