void VJSTimer::_SetTimer (VJSParms_callStaticFunction &ioParms, VJSWorker *inWorker, bool inIsInterval) { xbox_assert(inWorker != NULL); if (!ioParms.CountParams()) return; XBOX::VJSContext context(ioParms.GetContext()); XBOX::VJSObject functionObject(context); ioParms.GetParamObject(1, functionObject); if (!functionObject.IsFunction()) return; functionObject.Protect(); Real duration; duration = 0.0; if (ioParms.CountParams() >= 2) { if (ioParms.IsNumberParam(2)) { if (!ioParms.GetRealParam(2, &duration)) duration = 0.0; } else { // According to specification, if timeout is an object, call its toString() method if any. // Then apply ToNumber() on the string to obtain duration. XBOX::VJSObject timeOutObject(context); if (ioParms.GetParamObject(2, timeOutObject)) { timeOutObject.SetContext(context); if (timeOutObject.HasProperty("toString")) { XBOX::VJSObject toStringObject = timeOutObject.GetPropertyAsObject("toString"); if (toStringObject.IsFunction()) { std::vector<XBOX::VJSValue> values; XBOX::VJSValue string(context); toStringObject.SetContext(context); timeOutObject.CallFunction(toStringObject, &values, &string, NULL); if (string.IsString()) { // If Number() is called as a function (and not as a constructor), it acts as ToNumber(). // See section 15.7.1 of ECMA-262 specification. XBOX::VJSObject toNumberObject = context.GetGlobalObject().GetPropertyAsObject("Number"); if (toNumberObject.IsFunction()) { XBOX::VJSValue number(context); values.clear(); values.push_back(string); toNumberObject.SetContext(context); context.GetGlobalObject().CallFunction(toNumberObject, &values, &number, NULL); if (number.IsNumber() && !number.GetReal(&duration)) duration = 0.0; } } } } } } // (value != value) is true if value is a NaN. if (duration < 0.0 || duration > XBOX::kMAX_Real || duration != duration) duration = 0.0; } std::vector<XBOX::VJSValue> *arguments; arguments = new std::vector<XBOX::VJSValue>; for (sLONG i = 3; i <= ioParms.CountParams(); i++) arguments->push_back(ioParms.GetParamValue(i)); sLONG period, id; VJSTimer *timer; period = (sLONG) duration; if (inIsInterval) { if (period < VJSTimer::kMinimumInterval) period = VJSTimer::kMinimumInterval; } else { if (period < VJSTimer::kMinimumTimeout) period = VJSTimer::kMinimumTimeout; } timer = new VJSTimer(functionObject, inIsInterval ? period : VJSTimer::kTimeOut); if ((id = inWorker->GetTimerContext()->InsertTimer(timer)) < 0) { // Too many timers (should never happen). Silently ignore. // Returned ID (-1) isn't valid and a clear on it, will do nothing. timer->Release(); delete arguments; } else { XBOX::VTime triggerTime; triggerTime.FromSystemTime(); triggerTime.AddMilliseconds(period); inWorker->QueueEvent(VJSTimerEvent::Create(timer, triggerTime, arguments)); } ioParms.ReturnNumber(id); }
void VJSStream::_PutBinary (VJSParms_callStaticFunction &ioParms, XBOX::VStream *inStream) { xbox_assert(inStream != NULL); XBOX::VJSObject binaryObject(ioParms.GetContext()); if (!ioParms.GetParamObject(1, binaryObject)) { XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER, "1"); return; } bool isBuffer; VJSBufferObject *buffer; VJSDataSlice *dataSlice; const void *data; VSize size; if (binaryObject.IsOfClass(VJSBufferClass::Class())) { isBuffer = true; buffer = binaryObject.GetPrivateData<VJSBufferClass>(); xbox_assert(buffer != NULL); buffer->Retain(); data = buffer->GetDataPtr(); size = buffer->GetDataSize(); } else if (binaryObject.IsOfClass(VJSBlob::Class())) { VJSBlobValue *blob; isBuffer = false; blob = binaryObject.GetPrivateData<VJSBlob>(); xbox_assert(blob != NULL); dataSlice = blob->RetainDataSlice(); xbox_assert(dataSlice != NULL); data = dataSlice->GetDataPtr(); size = dataSlice->GetDataSize(); } else { XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER, "1"); return; } bool isOk; sLONG index, length; isOk = true; if (ioParms.CountParams() >= 2) { if (!ioParms.GetLongParam(2, &index)) { XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "2"); isOk = false; } } else index = 0; if (isOk && ioParms.CountParams() >= 3) { if (!ioParms.GetLongParam(3, &length)) { XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "3"); isOk = false; } } else { length = (sLONG) size; if (index > 0) length -= index; } // Silently ignore if out of bound. if (isOk && index >= 0 && length > 0 && index + length <= size) { XBOX::VError error; if ((error = inStream->PutData((uBYTE *) data + index, length)) != XBOX::VE_OK) XBOX::vThrowError(error); } if (isBuffer) buffer->Release(); else dataSlice->Release(); }
void VJSRequireClass::_evaluate (VJSParms_callStaticFunction &ioParms, void *) { XBOX::VJSContext context(ioParms.GetContext()); XBOX::VString fullPath; XBOX::VJSObject exportsObject(context), moduleObject(context); if (!ioParms.GetStringParam(1, fullPath)) { XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_STRING, "1"); return; } if (!ioParms.GetParamObject(2, exportsObject)) { XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_OBJECT, "2"); return; } if (!ioParms.GetParamObject(3, moduleObject)) { XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_OBJECT, "3"); return; } XBOX::VError error; XBOX::VURL url; XBOX::VString script; if ((error = VJSModuleState::LoadScript(fullPath, &url, &script)) != XBOX::VE_OK) { if (error == XBOX::VE_JVSC_SCRIPT_NOT_FOUND) { // Should not happen as require() does already check for existence. XBOX::vThrowError(XBOX::VE_JVSC_SCRIPT_NOT_FOUND, fullPath); } else XBOX::vThrowError(error); } else { XBOX::VFilePath path(fullPath, FPS_POSIX); XBOX::VFile *file; if ((file = new XBOX::VFile(path)) == NULL) { XBOX::vThrowError(XBOX::VE_MEMORY_FULL); } else { context.GetGlobalObjectPrivateInstance()->RegisterIncludedFile(file); XBOX::VString functionScript; XBOX::VJSValue functionResult(context); XBOX::JS4D::ExceptionRef exception; // Make a function of the module script, then call it. functionScript.AppendString("(function (exports, module) {"); functionScript.AppendString(script); functionScript.AppendString("})"); if (!context.EvaluateScript(functionScript, &url, &functionResult, &exception)) { ioParms.SetException(exception); // Syntax error. } else { xbox_assert(functionResult.IsFunction()); XBOX::VJSObject functionObject(context); std::vector<XBOX::VJSValue> arguments; XBOX::VJSValue result(context); functionObject.SetObjectRef((XBOX::JS4D::ObjectRef) functionResult.GetValueRef()); arguments.push_back(exportsObject); arguments.push_back(moduleObject); if (!context.GetGlobalObject().CallFunction(functionObject, &arguments, &result, &exception, &path)) ioParms.SetException(exception); else ioParms.ReturnValue(result); } XBOX::ReleaseRefCountable<XBOX::VFile>(&file); } } }