v8::Handle<v8::Value> JSEventHandlerStruct::getAllData() { v8::HandleScope handle_scope; bool isSusp = getIsSuspended(); bool isClear = getIsCleared(); v8::Local<v8::Object> returner =v8::Object::New(); returner->Set(v8::String::New("isCleared"),v8::Boolean::New(isClear)); returner->Set(v8::String::New("contextId"), v8::Integer::NewFromUnsigned(jscont->getContextID())); if (isClear) return handle_scope.Close(returner); returner->Set(v8::String::New("sender"), sender); returner->Set(v8::String::New("isSuspended"),v8::Boolean::New(isSusp)); v8::Handle<v8::Array> pattArray = v8::Array::New(); for (PatternListSize s =0; s < pattern.size(); ++s) pattArray->Set(v8::Number::New(s), pattern[s].getAllData()); returner->Set(v8::String::New("patterns"), pattArray); returner->Set(v8::String::New("callback"), cb); return handle_scope.Close(returner); }
void JSContextStruct::checkContextDisconnectCallback(JSPresenceStruct* jspres) { if (getIsSuspended() || getIsCleared()) return; if (hasOnDisconnectedCallback) jsObjScript->handlePresCallback(cbOnDisconnected,this,jspres); }
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); }
//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> 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(); }
void JSContextStruct::checkContextConnectCallback(JSPresenceStruct* jspres) { addToPresencesArray(jspres); //check whether should evaluate any further callbacks. if (getIsSuspended() || getIsCleared()) return; if (hasOnConnectedCallback) jsObjScript->handlePresCallback(cbOnConnected,this,jspres); }
JSEventHandlerStruct::~JSEventHandlerStruct() { if (! getIsCleared()) { if (jscont != NULL) jscont->struct_deregisterSuspendable(this); cb.Dispose(); sender.Dispose(); } }
//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); }
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(); }
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(); }
//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(); }
JSContextStruct::~JSContextStruct() { delete mSystem; delete mHomeObject; if (hasOnConnectedCallback) cbOnConnected.Dispose(); if (hasOnDisconnectedCallback) cbOnDisconnected.Dispose(); if (! getIsCleared()) mContext.Dispose(); }
//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 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> JSPresenceStruct::getAllData() { v8::HandleScope handle_scope; v8::Handle<v8::Object> returner = JSPositionListener::struct_getAllData(); uint32 contID = mContext->getContextID(); returner->Set(v8::String::New("isConnected"), v8::Boolean::New(isConnected)); returner->Set(v8::String::New("contextId"), v8::Integer::NewFromUnsigned(contID)); bool isclear = getIsCleared(); returner->Set(v8::String::New("isCleared"), v8::Boolean::New(isclear)); bool issusp = getIsSuspended(); returner->Set(v8::String::New("isSuspended"), v8::Boolean::New(issusp)); if (!v8::Context::InContext()) return v8::ThrowException(v8::Exception::Error(v8::String::New("Error in get all data of presences truct. not currently in a v8 context."))); v8::Handle<v8::Context>curContext = v8::Context::GetCurrent(); returner->Set(v8::String::New("suspendedOrientationVelocity"),CreateJSResult(curContext,mSuspendedOrientationVelocity)); returner->Set(v8::String::New("suspendedVelocity"),CreateJSResult(curContext,mSuspendedVelocity)); //onConnected if (mOnConnectedCallback.IsEmpty()) returner->Set(v8::String::New("connectCallback"), v8::Null()); else returner -> Set(v8::String::New("connectCallback"), mOnConnectedCallback); //prox removed if (mOnProxRemovedEventHandler.IsEmpty()) returner->Set(v8::String::New("onProxRemovedEventHandler"), v8::Null()); else returner->Set(v8::String::New("onProxRemovedEventHandler"), mOnProxRemovedEventHandler); //prox added func if (mOnProxAddedEventHandler.IsEmpty()) returner->Set(v8::String::New("onProxAddedEventHandler"), v8::Null()); else returner->Set(v8::String::New("onProxAddedEventHandler"), mOnProxAddedEventHandler); return handle_scope.Close(returner); }
//returning all data necessary to re-generate timer // uint32 contextId // double period // double timeUntil timer expires // bool isSuspended // bool isCleared // func cb v8::Handle<v8::Value> JSTimerStruct::struct_getAllData() { v8::HandleScope handle_scope; uint32 contId = jsContStruct->getContextID(); bool issusp = getIsSuspended(); bool isclear = getIsCleared(); double period = -1; double tUntil = -1; v8::Handle<v8::Function> cbFunc; if (! isclear) { cbFunc = cb; period = timeUntil.toSeconds(); if (issusp) tUntil = timeUntil.toSeconds(); else { Duration pt = mDeadlineTimer->expiresFromNow(); tUntil = pt.seconds(); } } v8::Handle<v8::Object> returner = v8::Object::New(); if (isclear) { returner->Set(v8::String::New("isCleared"),v8::Boolean::New(isclear)); returner->Set(v8::String::New("contextId"), v8::Integer::NewFromUnsigned(contId)); return handle_scope.Close(returner); } returner->Set(v8::String::New("period"), v8::Number::New(period)); returner->Set(v8::String::New("callback"),cbFunc); returner->Set(v8::String::New("timeRemaining"),v8::Number::New(tUntil)); returner->Set(v8::String::New("isSuspended"),v8::Boolean::New(issusp)); return handle_scope.Close(returner); }
void JSEventHandlerStruct::printHandler() { if (getIsCleared()) { std::cout<<"**Cleared. No information."; return; } //print patterns for (PatternList::const_iterator pat_it = pattern.begin(); pat_it != pattern.end(); pat_it++) { if (getIsSuspended()) std::cout<<"**Suspended "; else std::cout<<"**Active "; pat_it->printPattern(); } /* FIXME: sender should really be a part of the pattern. */ //print sender if (this->sender->IsNull()) std::cout<<"Sender: any"; else { //unwrap the sender to match v8::Local<v8::External>wrap; void* ptr; wrap= v8::Local<v8::External>::Cast(this->sender->GetInternalField(0)); ptr = wrap->Value(); ObjectReference* objRef = static_cast<ObjectReference*>(ptr); std::cout<<"Sender: "<<(objRef->getAsUUID()).toString(); } std::cout<<"\n\n"; }
//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 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); }
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); }