more hacking on script shutdown behavior

This commit is contained in:
ZappoMan 2015-02-24 14:02:46 -08:00
parent 6be8f4c0ec
commit fd93b99f03
4 changed files with 231 additions and 57 deletions

View file

@ -3552,9 +3552,11 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded,
bool loadScriptFromEditor, bool activateMainWindow) {
qDebug() << "Application::loadScript() " << scriptFilename << "line:" << __LINE__;
qDebug() << "Application::loadScript() ---- BEGIN ---- Script:" << scriptFilename;
if (isAboutToQuit()) {
qDebug() << "Application::loadScript() WHILE QUITTING.... what to do????" << scriptFilename << "line:" << __LINE__;
qDebug() << "Requests to load scripts while quitting are ignored. Script:" << scriptFilename;
qDebug() << "Application::loadScript() ---- END ---- Script:" << scriptFilename;
return NULL;
}
@ -3563,6 +3565,8 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor
&& !_scriptEnginesHash[scriptURLString]->isFinished()) {
qDebug() << "Application::loadScript() from _scriptEnginesHash[scriptURLString].... Script:" << scriptFilename;
qDebug() << "Application::loadScript() ---- END ---- Script:" << scriptFilename;
return _scriptEnginesHash[scriptURLString];
}
@ -3581,6 +3585,7 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError);
// get the script engine object to load the script at the designated script URL
qDebug() << "Application::loadScript() about to call loadURL() scriptUrl:" << scriptUrl;
scriptEngine->loadURL(scriptUrl);
}
@ -3589,6 +3594,9 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
_window->activateWindow();
}
qDebug() << "Application::loadScript() newly created scriptEngine.... Script:" << scriptFilename;
qDebug() << "Application::loadScript() ---- END ---- Script:" << scriptFilename;
return scriptEngine;
}

View file

@ -59,10 +59,8 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
}
EntityTreeRenderer::~EntityTreeRenderer() {
qDebug() << "EntityTreeRenderer::~EntityTreeRenderer() -------- BEGIN -----------";
// NOTE: we don't need to delete _entitiesScriptEngine because it's owned by the application and gets cleaned up
// automatically but we do need to delete our sandbox script engine.
if (_sandboxScriptEngine) {
// NOTE: is it possible this is a problem? I think that we hook the script engine object up to a deleteLater()
// call inside of registerScriptEngineWithApplicationServices() but do we not call that for _sandboxScriptEngine???
@ -72,7 +70,6 @@ EntityTreeRenderer::~EntityTreeRenderer() {
delete _sandboxScriptEngine;
_sandboxScriptEngine = NULL;
}
qDebug() << "EntityTreeRenderer::~EntityTreeRenderer() -------- DONE -----------";
}
void EntityTreeRenderer::clear() {

View file

@ -94,33 +94,32 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
_isUserLoaded(false),
_arrayBufferClass(new ArrayBufferClass(this))
{
qDebug() << "ScriptEngine::ScriptEngine() " << getFilename() << "[" << ((void*)this) << "]" << " -------- BEGIN -----------";
_allScriptsMutex.lock();
_allKnownScriptEngines.insert(this);
_allScriptsMutex.unlock();
qDebug() << "ScriptEngine::ScriptEngine() " << getFilename() << " -------- DONE -----------";
}
ScriptEngine::~ScriptEngine() {
qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << "[" << ((void*)this) << "]" << " -------- BEGIN -----------";
qDebug() << "ScriptEngine::~ScriptEngine() ------- BEGIN ------- script:" << getFilename();
// If we're not already in the middle of stopping all scripts, then we should remove ourselves
// from the list of running scripts. We don't do this if we're in the process of stopping all scripts
// because that method removes scripts from its list as it iterates them
if (!_stoppingAllScripts) {
_allScriptsMutex.lock();
qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << " removing from list of scripts";
_allKnownScriptEngines.remove(this);
_allScriptsMutex.unlock();
} else {
qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << " NOT removing from list of scripts here...";
}
qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << " -------- DONE -----------";
qDebug() << "ScriptEngine::~ScriptEngine() ------- END ------- script:" << getFilename();
}
QSet<ScriptEngine*> ScriptEngine::_allKnownScriptEngines;
QMutex ScriptEngine::_allScriptsMutex;
bool ScriptEngine::_stoppingAllScripts = false;
bool ScriptEngine::_doneRunningThisScript = false;
void ScriptEngine::stopAllScripts(QObject* application) {
qDebug() << "ScriptEngine::stopAllScripts() ------- BEGIN -------";
qDebug() << "ScriptEngine::stopAllScripts() -------- BEGIN -----------";
_allScriptsMutex.lock();
_stoppingAllScripts = true;
@ -128,44 +127,92 @@ void ScriptEngine::stopAllScripts(QObject* application) {
while (i.hasNext()) {
ScriptEngine* scriptEngine = i.next();
qDebug() << "ScriptEngine::stopAllScripts() scriptEngine: " << (void*)scriptEngine;
QString scriptName = scriptEngine->getFilename();
qDebug() << "ScriptEngine::stopAllScripts() considering script: " << scriptName << "evaluatePending:" << scriptEngine->evaluatePending();
qDebug() << "ScriptEngine::stopAllScripts() considering:" << scriptName
<< "isRunning():" << scriptEngine->isRunning()
<< "evaluatePending():" << scriptEngine->evaluatePending();
// NOTE: typically all script engines are running. But there's at least one known exception to this, the
// "entities sandbox" which is only used to evaluate entities scripts to test their validity before using
// them. We don't need to stop scripts that aren't running.
if (scriptEngine->isRunning()) {
// If the script is running, but still evaluating then we need to wait for its evaluation step to
// complete. After that we can handle the stop process appropriately
if (scriptEngine->evaluatePending()) {
qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__ << "waiting for evaluation to complete....";
QEventLoop loop;
QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit);
loop.exec();
qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__ << "evaluation complete....";
while (scriptEngine->evaluatePending()) {
QEventLoop loop;
QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit);
qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) STARTING loop.exec() script:" << scriptName;
loop.exec();
qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) AFTER loop.exec() script:" << scriptName;
}
}
qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__;
QEventLoop loop;
QObject::connect(scriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit);
qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__;
scriptEngine->disconnect(application);
qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__;
scriptEngine->stop();
qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__;
loop.exec();
qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__;
qDebug() << "ScriptEngine::stopAllScripts() -- WAITING for waitTillDoneRunning() script:" << scriptName;
scriptEngine->waitTillDoneRunning();
qDebug() << "ScriptEngine::stopAllScripts() -- AFTER waitTillDoneRunning() script:" << scriptName;
i.remove();
} else {
qDebug() << "ScriptEngine::stopAllScripts() script: " << scriptName << " was not running... skipping it's stop() call.";
}
}
_stoppingAllScripts = false;
_allScriptsMutex.unlock();
qDebug() << "ScriptEngine::stopAllScripts() -------- DONE -----------";
qDebug() << "ScriptEngine::stopAllScripts() ------- DONE -------";
}
void ScriptEngine::waitTillDoneRunning() {
QString scriptName = getFilename();
qDebug() << "ScriptEngine::waitTillDoneRunning() ------- BEGIN ------- script:" << scriptName;
qDebug() << " _isFinished:" << _isFinished;
qDebug() << " _isRunning:" << _isRunning;
qDebug() << " _isInitialized:" << _isInitialized;
qDebug() << " _evaluatesPending:" << _evaluatesPending;
if (_isRunning) {
qDebug() << "ScriptEngine::waitTillDoneRunning() SETTING _doneRunningThisScript = false ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
_doneRunningThisScript = false;
_isWaitingForDoneRunning = true;
// What can we do here???
// we will be calling this on the main Application thread, inside of stopAllScripts()
// we want the application thread to continue to process events, because the script will
// likely need to marshall messages across to the main thread.
while (!_doneRunningThisScript && _isRunning) {
// and run a QEventLoop???
QEventLoop loop;
QObject::connect(this, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit);
qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING loop.exec() script:" << scriptName;
qDebug() << " _doneRunningThisScript:" << _doneRunningThisScript;
qDebug() << " _isRunning:" << _isRunning;
qDebug() << " _isWaitingForDoneRunning:" << _isWaitingForDoneRunning;
qDebug() << " _isFinished:" << _isFinished;
qDebug() << " _isInitialized:" << _isInitialized;
qDebug() << " _evaluatesPending:" << _evaluatesPending;
loop.exec();
qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER loop.exec() script:" << scriptName;
// process events
qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING QCoreApplication::processEvents() script:" << scriptName;
QCoreApplication::processEvents();
qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER QCoreApplication::processEvents() script:" << scriptName;
if (_doneRunningThisScript) {
qDebug() << "ScriptEngine::waitTillDoneRunning() _doneRunningThisScript after processEvents... breaking!!! script:" << scriptName;
break;
}
}
_isWaitingForDoneRunning = false;
}
qDebug() << "ScriptEngine::waitTillDoneRunning() ------- DONE ------- script:" << scriptName;
}
QString ScriptEngine::getFilename() const {
@ -377,12 +424,23 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func
}
void ScriptEngine::evaluate() {
if (_stoppingAllScripts) {
qDebug() << "ScriptEngine::evaluate() while shutting down is ignored...";
qDebug() << " parent script:" << getFilename() << "[" << this << "]";
return; // bail early
}
qDebug() << "ScriptEngine::evaluate() -- BEGIN script:" << getFilename() << "[" << this << "]";
if (!_isInitialized) {
init();
}
qDebug() << "ScriptEngine::evaluate() -- about to call own evaluate(program) script:" << getFilename() << "[" << this << "]";
QScriptValue result = evaluate(_scriptContents);
qDebug() << "ScriptEngine::evaluate() -- AFTER own evaluate(program) script:" << getFilename() << "[" << this << "]";
// TODO: why do we check this twice? It seems like the call to clearExcpetions() in the lower level evaluate call
// will cause this code to never actually run...
if (hasUncaughtException()) {
int line = uncaughtExceptionLineNumber();
qDebug() << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << result.toString();
@ -392,17 +450,30 @@ void ScriptEngine::evaluate() {
}
QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) {
qDebug() << "ScriptEngine::evaluate() " << getFilename() << " line:" << __LINE__;
_evaluatePending = true;
if (_stoppingAllScripts) {
qDebug() << "ScriptEngine::evaluate(program) while shutting down is ignored...";
qDebug() << " parent script:" << getFilename() << "[" << this << "]";
return QScriptValue(); // bail early
}
qDebug() << "ScriptEngine::evaluate(program) -- BEGIN script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";
_evaluatesPending++;
qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending++ script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";
qDebug() << "ScriptEngine::evaluate(program) -- BEFORE QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";
QScriptValue result = QScriptEngine::evaluate(program, fileName, lineNumber);
qDebug() << "ScriptEngine::evaluate(program) -- AFTER QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";
if (hasUncaughtException()) {
int line = uncaughtExceptionLineNumber();
qDebug() << "Uncaught exception at (" << _fileNameString << " : " << fileName << ") line" << line << ": " << result.toString();
}
_evaluatesPending--;
qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending-- script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";
qDebug() << "ScriptEngine::evaluate(program) -- ABOUT TO emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";
emit evaluationFinished(result, hasUncaughtException());
qDebug() << "ScriptEngine::evaluate(program) -- AFTER emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";
clearExceptions();
_evaluatePending = false;
qDebug() << "ScriptEngine::evaluate() " << getFilename() << " line:" << __LINE__;
qDebug() << "ScriptEngine::evaluate(program) -- DONE script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";
return result;
}
@ -419,49 +490,60 @@ void ScriptEngine::sendAvatarBillboardPacket() {
}
void ScriptEngine::run() {
qDebug() << "ScriptEngine::run() " << getFilename() << " -------- BEGIN -----------";
// TODO: can we add a short circuit for _stoppingAllScripts here? What does it mean to not start running if
// we're in the process of stopping?
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
if (!_isInitialized) {
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
init();
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
}
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
_isRunning = true;
_isFinished = false;
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
emit runningStateChanged();
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
QScriptValue result = evaluate(_scriptContents);
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
QElapsedTimer startTime;
startTime.start();
int thisFrame = 0;
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
auto nodeList = DependencyManager::get<NodeList>();
qint64 lastUpdate = usecTimestampNow();
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
while (!_isFinished) {
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec
if (usecToSleep > 0) {
usleep(usecToSleep);
}
if (_isFinished) {
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
break;
}
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
QCoreApplication::processEvents();
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
if (_isFinished) {
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
break;
}
@ -589,16 +671,38 @@ void ScriptEngine::run() {
emit update(deltaTime);
}
lastUpdate = now;
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
}
qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__;
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
stopAllTimers(); // make sure all our timers are stopped if the script is ending
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename();
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
emit scriptEnding();
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
// kill the avatar identity timer
delete _avatarIdentityTimer;
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) {
// release the queue of edit entity messages.
_entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages();
@ -609,19 +713,44 @@ void ScriptEngine::run() {
}
}
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
// If we were on a thread, then wait till it's done
if (thread()) {
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
thread()->quit();
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
emit finished(_fileNameString);
_isRunning = false;
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
_isRunning = false;
emit runningStateChanged();
qDebug() << "ABOUT TO emit doneRunning() script:" << getFilename() << "[" << this << "]";
emit doneRunning();
qDebug() << "ScriptEngine::run() " << getFilename() << " -------- DONE -----------" << " line:" << __LINE__;
qDebug() << "AFTER emit doneRunning() script:" << getFilename() << "[" << this << "]";
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
qDebug() << "ScriptEngine::run() SETTING _doneRunningThisScript = true ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
_doneRunningThisScript = true;
if (_isWaitingForDoneRunning) {
qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";
}
}
// NOTE: This is private because it must be called on the same thread that created the timers, which is why
@ -636,9 +765,10 @@ void ScriptEngine::stopAllTimers() {
}
void ScriptEngine::stop() {
qDebug() << "ScriptEngine::stop() " << getFilename() << "[" << ((void*)this) << "]";
qDebug() << "ScriptEngine::stop() -- START -- line:" << __LINE__ << " script:" << getFilename();
_isFinished = true;
emit runningStateChanged();
qDebug() << "ScriptEngine::stop() -- DONE -- line:" << __LINE__ << " script:" << getFilename();
}
void ScriptEngine::timerFired() {
@ -674,10 +804,22 @@ QObject* ScriptEngine::setupTimerWithInterval(const QScriptValue& function, int
}
QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) {
if (_stoppingAllScripts) {
qDebug() << "Script.setInterval() while shutting down is ignored...";
qDebug() << " parent script:" << getFilename() << "[" << this << "]";
return NULL; // bail early
}
return setupTimerWithInterval(function, intervalMS, false);
}
QObject* ScriptEngine::setTimeout(const QScriptValue& function, int timeoutMS) {
if (_stoppingAllScripts) {
qDebug() << "Script.setTimeout() while shutting down is ignored...";
qDebug() << " parent script:" << getFilename() << "[" << this << "]";
return NULL; // bail early
}
return setupTimerWithInterval(function, timeoutMS, true);
}
@ -723,6 +865,12 @@ void ScriptEngine::print(const QString& message) {
// If no callback is specified, the included files will be loaded synchronously and will block execution until
// all of the files have finished loading.
void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callback) {
if (_stoppingAllScripts) {
qDebug() << "Script.include() while shutting down is ignored...";
qDebug() << " includeFiles:" << includeFiles;
qDebug() << " parent script:" << getFilename() << "[" << this << "]";
return; // bail early
}
QList<QUrl> urls;
for (QString file : includeFiles) {
urls.append(resolvePath(file));
@ -736,7 +884,9 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
if (contents.isNull()) {
qDebug() << "Error loading file: " << url;
} else {
qDebug() << "ScriptEngine::include() BEFORE evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending;
QScriptValue result = evaluate(contents, url.toString());
qDebug() << "ScriptEngine::include() AFTER evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending;
}
}
@ -762,17 +912,31 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
}
void ScriptEngine::include(const QString& includeFile, QScriptValue callback) {
if (_stoppingAllScripts) {
qDebug() << "Script.include() while shutting down is ignored...";
qDebug() << " includeFile:" << includeFile;
qDebug() << " parent script:" << getFilename() << "[" << this << "]";
return; // bail early
}
QStringList urls;
urls.append(includeFile);
include(urls, callback);
}
// NOTE: The load() command is similar to the include() command except that it loads the script
// as a stand-alone script. To accomplish this, the ScriptEngine class just emits a signal which
// the Application or other context will connect to in order to know to actually load the script
void ScriptEngine::load(const QString& loadFile) {
qDebug() << "ScriptEngine::load() " << getFilename() << "[" << ((void*)this) << "]" << "line:" << __LINE__;
if (_stoppingAllScripts) {
qDebug() << "Script.load() while shutting down is ignored...";
qDebug() << " loadFile:" << loadFile;
qDebug() << " parent script:" << getFilename() << "[" << this << "]";
return; // bail early
}
QUrl url = resolvePath(loadFile);
qDebug() << "ScriptEngine::load() " << getFilename() << "[" << ((void*)this) << "]" << "line:" << __LINE__;
emit loadScript(url.toString(), false);
qDebug() << "ScriptEngine::load() " << getFilename() << "[" << ((void*)this) << "]" << "line:" << __LINE__;
}
void ScriptEngine::nodeKilled(SharedNodePointer node) {

View file

@ -16,6 +16,7 @@
#include <QtCore/QObject>
#include <QtCore/QUrl>
#include <QtCore/QWaitCondition>
#include <QtScript/QScriptEngine>
#include <AnimationCache.h>
@ -85,7 +86,7 @@ public:
bool isFinished() const { return _isFinished; }
bool isRunning() const { return _isRunning; }
bool evaluatePending() const { return _evaluatePending; }
bool evaluatePending() const { return _evaluatesPending > 0; }
void setUserLoaded(bool isUserLoaded) { _isUserLoaded = isUserLoaded; }
bool isUserLoaded() const { return _isUserLoaded; }
@ -95,6 +96,8 @@ public:
QString getFilename() const;
static void stopAllScripts(QObject* application);
void waitTillDoneRunning();
public slots:
void loadURL(const QUrl& scriptURL);
@ -132,7 +135,8 @@ protected:
QString _parentURL;
bool _isFinished;
bool _isRunning;
bool _evaluatePending = false;
int _evaluatesPending = 0;
bool _isWaitingForDoneRunning = false;
bool _isInitialized;
bool _isAvatar;
QTimer* _avatarIdentityTimer;
@ -171,6 +175,7 @@ private:
static QSet<ScriptEngine*> _allKnownScriptEngines;
static QMutex _allScriptsMutex;
static bool _stoppingAllScripts;
static bool _doneRunningThisScript;
};
#endif // hifi_ScriptEngine_h