//sender should be of type VISIBLE (see template defined in JSObjectScriptManager bool JSEventHandlerStruct::matches(v8::Handle<v8::Object> obj, v8::Handle<v8::Object> incoming_sender, const SpaceObjectReference& receiver) { if (getIsSuspended() || getIsCleared()) return false; //cannot match a suspended handler //decode the sender of the message String errorMessage = "[JS] Error encountered in matches of JSEventHandler. Failed to decode sender of message as a visible object. "; JSPositionListener* jsposlist = decodeJSPosListener(incoming_sender,errorMessage); if (jsposlist == NULL) { JSLOG(error,errorMessage); return false; } SpaceObjectReference* spref1 = jsposlist->getToListenTo(); //decode the expected sender if (! sender->IsNull()) { String errorMessageExpectedSender = "[JS] Error encountered in matches of JSEventHandler. Failed to decode expected sender of event handler. "; JSPositionListener* jsplExpectedSender = decodeJSPosListener(sender, errorMessageExpectedSender); if (jsplExpectedSender == NULL) { JSLOG(error,errorMessageExpectedSender); return false; } SpaceObjectReference* spref2 = jsplExpectedSender->getToListenTo(); //check if the senders match if ( (*spref1) != (*spref2)) //the senders do not match. do not fire return false; } //check if the pattern matches the obj for(PatternList::const_iterator pat_it = pattern.begin(); pat_it != pattern.end(); pat_it++) { if (! pat_it->matches(obj)) return false; } //check if the message is *to* one of my presences if (jscont->canReceiveMessagesFor(receiver)) return true; return false; }
v8::Handle<v8::Value> JSContextStruct::suspend() { if (getIsCleared()) { JSLOG(error,"Error when suspending. This context object was already cleared."); return v8::ThrowException( v8::Exception::Error(v8::String::New("Error. Cannot suspend a context that has already been cleared.")) ); } JSLOG(insane,"Suspending all suspendable objects associated with context"); for (SuspendableIter iter = associatedSuspendables.begin(); iter != associatedSuspendables.end(); ++iter) iter->first->suspend(); return JSSuspendable::suspend(); }
void JSWhenWatchedListStruct::debugPrintWatchedList() { JSLOG(debug,"printing all elements of when watched list."); for (JSWhenWatchedIter iter = mItemsToWatch.begin(); iter!= mItemsToWatch.end(); ++iter) (*iter)->debugPrint(); }
bool Capabilities::givesCap(CapNum capabilitiesNum, Caps checkingCap, JSPresenceStruct* ctxPres, JSPresenceStruct* onPres) { if (! presenceSpecificCap(checkingCap)) return (capabilitiesNum & checkingCap); //means its a presence-specific capability: should only return false if //trying to perform operation on presence passed through to sandbox and //if capability is not granted to that sandbox. if (onPres == NULL) { JSLOG(error, "Error in checking whether given a capability. " <<\ "Checking a presence-specific capability, but provided no " <<\ "presence to check against. Cap: " << (int)checkingCap); } //ctxPres can be null when executing from root context if ((ctxPres == NULL) || (onPres == NULL)) return true; if (ctxPres == onPres) { //check if given capability return (capabilitiesNum & checkingCap); } return true; }
void JSContextStruct::struct_registerSuspendable (JSSuspendable* toRegister) { if (getIsCleared()) { JSLOG(error,"Error when registering suspendable. This context object was already cleared."); return; } SuspendableIter iter = associatedSuspendables.find(toRegister); if (iter != associatedSuspendables.end()) { JSLOG(info,"Strangeness in registerSuspendable of JSContextStruct. Trying to re-register a suspendable with the context that was already registered. Unlikely to be an error, but thought I should mention it."); return; } associatedSuspendables[toRegister] = 1; }
v8::Handle<v8::Value> JSTimerStruct::clear() { if (getIsCleared()) { JSLOG(insane,"In JSTimerStruct, calling clear on a timer that has already been cleared."); return JSSuspendable::clear(); } v8::HandleScope handle_scope; JSSuspendable::clear(); mDeadlineTimer->cancel(); if (! cb.IsEmpty()) cb.Dispose(); if (! mPersistentHandle.IsEmpty()) { //check to make sure object has adequate number of fields. CHECK_INTERNAL_FIELD_COUNT(mPersistentHandle,jstimer,TIMER_JSTIMER_TEMPLATE_FIELD_COUNT, v8::Boolean::New(true)); //delete typeId, and return if have incorrect params for type id DEL_TYPEID_AND_CHECK(mPersistentHandle,jstimer,TIMER_TYPEID_STRING,v8::Boolean::New(true)); mPersistentHandle->SetInternalField(TIMER_JSTIMERSTRUCT_FIELD, External::New(NULL)); } // Be careful after this! JSContextStruct::struct_deregisterSuspendable will // delete this object so you shouldn't use any member variables after // invoking it. if (jsContStruct != NULL) { //cannot clear if amExecuting. if (amExecuting) { mCtx->objStrand->post( std::tr1::bind(&JSContextStruct::struct_asyncDeregisterSuspendable,jsContStruct,this, jsContStruct->livenessToken(),livenessToken()), "JSContextStruct::struct_asyncDeregisterSuspendable" ); } else jsContStruct->struct_deregisterSuspendable(this); } // Note that since this allows the JS GC thread to destroy this object // in response to all references to it being lost, // we need to make sure it is absolutely the *last* operation we do on // member variables. // In this case, the above call will have deleted this JSTimerStruct, so we // don't even set it at all. It would have been unsafe to set it earlier // because we could have ended up with two threads trying to do the deletion. //noTimerWaiting = true; return v8::Boolean::New(true); }
void JSSystemStruct::stripCapEscalation(Capabilities::CapNum& permNum, Capabilities::Caps capRequesting, JSPresenceStruct* jspres, const String& capRequestingName) { if (! checkCurCtxtHasCapability(jspres,capRequesting)) { /*means trying to set this capability when don't have it in the base*/ /*sandbox. We should strip it.*/ JSLOG(info,"Trying to exceed capability " + capRequestingName + " when creating sandbox. Stripping this capability"); permNum -= capRequesting; } }
v8::Handle<v8::Value> JSEventHandlerStruct::resume() { if (getIsCleared()) { JSLOG(info, "Error in resume of JSEventHandlerStruct.cpp. Called resume even though the handler had previously been cleared."); return v8::ThrowException( v8::Exception::Error(v8::String::New("Error. Called resume on a handler that had already been cleared."))); } return JSSuspendable::resume(); }
//called from jsobjectscript. void JSPresenceStruct::disconnectCalledFromObjScript() { if (getIsCleared()) return; if (! getIsConnected()) JSLOG(error, "Error when calling disconnect on presence. The presence wasn't already connected."); isConnected = false; if (mContext != NULL) mContext->checkContextDisconnectCallback(this); }
void JSContextStruct::struct_deregisterSuspendable (JSSuspendable* toDeregister) { //don't want to de-register suspendables while I'm calling clear. //clear is already running through each and removing them from suspendables. if (inClear) return; if (getIsCleared()) { JSLOG(error,"Error when deregistering suspendable. This context object was already cleared."); return; } SuspendableIter iter = associatedSuspendables.find(toDeregister); if (iter == associatedSuspendables.end()) { JSLOG(error,"Error when deregistering suspendable in JSContextStruct.cpp. Trying to deregister a suspendable that the context struct had not already registered. Likely an error."); return; } associatedSuspendables.erase(iter); }
//has more of a reset-type functionality than resume //if the time has not been cleared, then, cancel the current timer, //and start a new countdown to execute the callback. v8::Handle<v8::Value> JSTimerStruct::resume() { if (getIsCleared()) { JSLOG(info,"Error in JSTimerStruct. Trying to resume a timer object that has already been cleared. Taking no action"); return JSSuspendable::getIsSuspendedV8(); } mDeadlineTimer->cancel(); noTimerWaiting=false; mDeadlineTimer->wait(timeUntil,std::tr1::bind(&JSTimerStruct::evaluateCallback,this)); return JSSuspendable::resume(); }
v8::Handle<v8::Value> JSTimerStruct::suspend() { if (getIsCleared()) { JSLOG(info, "Error in suspend of JSTimerStruct.cpp. Called suspend even though the timer had previously been cleared."); return v8::ThrowException( v8::Exception::Error(v8::String::New("Error. Called suspend on a timer that had already been cleared."))); } JSLOG(insane,"suspending timer"); //note, it is important that call to JSSuspendable::supsend occurs before //actually cancelling the deadline timer so that we're performing correct //checks for timer cleanup. v8::HandleScope handle_scope; v8::Handle<v8::Value>returner = JSSuspendable::suspend(); mDeadlineTimer->cancel(); // Note that since this allows the JS GC thread to destroy this object // in response to all references to it being lost, // we need to make sure it is absolutely the *last* operation we do on // member variables. noTimerWaiting = true; return handle_scope.Close(returner); }
v8::Handle<v8::Value> JSTimerStruct::struct_resetTimer(double timeInSecondsToRefire) { if (getIsCleared()) { JSLOG(info,"Error in JSTimerStruct. Calling reset on a timer that has already been cleared."); return JSSuspendable::clear(); } mDeadlineTimer->cancel(); noTimerWaiting=false; mDeadlineTimer->wait(Duration::seconds(timeInSecondsToRefire),std::tr1::bind(&JSTimerStruct::evaluateCallback,this)); return JSSuspendable::resume(); }
//this function asks the jsObjScript to send a message from the presence associated //with associatedPresence to the object with spaceobjectreference mHomeObject. //The message contains the object toSend. v8::Handle<v8::Value> JSContextStruct::struct_sendHome(const String& toSend) { NullPresenceCheck("Context: sendHome"); if (getIsCleared()) { JSLOG(error,"Error when sending home. This context object was already cleared."); return v8::ThrowException( v8::Exception::Error(v8::String::New("Error. Cannot call sendHome from a context that has already been cleared.")) ); } jsObjScript->sendMessageToEntity(mHomeObject,associatedPresence->getSporef(),toSend); return v8::Undefined(); }
void JSPresenceStruct::connect(const SpaceObjectReference& _sporef) { v8::HandleScope handle_scope; if (getIsConnected()) { JSLOG(error, "Error when calling connect on presence. The presence was already connected."); deregisterAsPosAndMeshListener(); } isConnected = true; JSPositionListener::setListenTo(&_sporef,NULL); JSPositionListener::registerAsPosAndMeshListener(); callConnectedCallback(); }
//dist(a,b) < g //timeToEval is going to be when the above condition will first be true. bool JSWhenPred::whenToEval(JSVisibleStruct* a, JSVisibleStruct* b, float g, float& timeToEval) { Vector3d posA = a->returnProxyPositionCPP(); Vector3d posB = b->returnProxyPositionCPP(); Vector3d velA = a->returnProxyVelocityCPP(); Vector3d velB = b->returnProxyVelocityCPP(); float root1, root2; bool hasRoot = computeDistPredFirstRoot( posA.x - posB.x,velA.x - velB.x, posA.y - posB.y,velA.y - velB.y, posA.z - posB.z,velA.z - velB.z, root1, root2); if ( ! ((a->getStillVisibleCPP()) && (b->getStillVisibleCPP()))) JSLOG(info,"Warning. Evaluating when predicate for object that is not visible"); if ((root1>=0) && (root2 <0)) { timeToEval = root1; return true; } if ((root2>=0) && (root1 <0)) { timeToEval = root2; return true; } if ((root1 >= 0) && (root1 <= root2)) { timeToEval = root1; return true; } if ((root2 >=0) && (root2<=root1)) { timeToEval = root2; return true; } return false; }
//Destroys all objects that were created in this context + all of this context's //subcontexts. v8::Handle<v8::Value> JSContextStruct::clear() { inClear = true; JSLOG(insane,"Clearing a context. Hopefully it works!"); for (SuspendableIter iter = associatedSuspendables.begin(); iter != associatedSuspendables.end(); ++iter) iter->first->clear(); systemObj.Dispose(); if (hasOnConnectedCallback) cbOnConnected.Dispose(); if (hasOnDisconnectedCallback) cbOnDisconnected.Dispose(); mContext.Dispose(); inClear = false; return JSSuspendable::clear(); }
//first argument of args is a function (funcToCall), which we skip v8::Handle<v8::Value> JSContextStruct::struct_executeScript(v8::Handle<v8::Function> funcToCall,const v8::Arguments& args) { if (getIsCleared()) { JSLOG(error,"Error when executing. This context object was already cleared."); return v8::ThrowException( v8::Exception::Error(v8::String::New("Error. Cannot call execute on a context that has already been cleared.")) ); } //copying arguments over to arg array for execution. int argc = args.Length() -1; Handle<Value>* argv = new Handle<Value>[argc]; for (int s=1; s < args.Length(); ++s) argv[s-1] = args[s]; v8::Handle<v8::Value> returner = jsObjScript->executeInContext(mContext,funcToCall, argc,argv); delete argv; //free additional memory. return returner; }
void JSTimerStruct::iEvaluateCallback(Liveness::Token token) { //lkjs; FIXME: Can weak reference clean up a timer //while it's in this function? (If we try to use lock, we run //into a problem when the timer tries to clear itself.) if (!token) return; if (mCtx->stopped()) { JSLOG(warn, "Timer evaluateCallback invoked after stop request, ignoring..."); noTimerWaiting=true; // Allow cleanup, see notes below return; } while(!mCtx->initialized()) {} amExecuting = true; emerScript->invokeCallbackInContext(emerScript->livenessToken(), cb, jsContStruct); //if we were told to kill the timer after firing, then check kill conditions //again in noReference. if (killAfterFire) { mCtx->objStrand->post( std::tr1::bind(&JSTimerStruct::noReference,this, livenessToken()), "JSTimerStruct::noReference" ); } //means that we have no pending timer operation. // Note that since this allows the JS GC thread to destroy this object // in response to all references to it being lost, // we need to make sure it is absolutely the *last* operation we do on // member variables. noTimerWaiting=true; amExecuting = false; }
void JSTimerStruct::evaluateCallback() { Liveness::Token token=mLiveness.livenessToken(); emerScript->invokeCallbackInContext(emerScript->livenessToken(), cb, jsContStruct); if (token) { if (mContext->stopped()) { JSLOG(warn, "Timer evaluateCallback invoked after stop request, ignoring..."); noTimerWaiting=true; // Allow cleanup, see notes below return; } //if we were told to kill the timer after firing, then check kill conditions //again in noReference. if (killAfterFire) mContext->mainStrand->post(std::tr1::bind(&JSTimerStruct::noReference,this,token)); //means that we have no pending timer operation. // Note that since this allows the JS GC thread to destroy this object // in response to all references to it being lost, // we need to make sure it is absolutely the *last* operation we do on // member variables. noTimerWaiting=true; } }
void JSContextStruct::presenceDied() { JSLOG(error,"[JS] Incorrectly handling presence destructions in context struct. Need additional code."); }