Added simple compile test function

This commit is contained in:
ksuprynowicz 2022-10-15 12:38:51 +02:00
parent 38064b95c5
commit 827ddf5958
7 changed files with 83 additions and 19 deletions

View file

@ -85,7 +85,7 @@ public:
virtual bool hasUncaughtException() const = 0;
virtual bool isEvaluating() const = 0;
//virtual ScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1) = 0;
virtual ScriptValue cheskScriptSyntax(ScriptProgramPointer program) = 0;
virtual ScriptValue checkScriptSyntax(ScriptProgramPointer program) = 0;
virtual ScriptValue makeError(const ScriptValue& other = ScriptValue(), const QString& type = "Error") = 0;
virtual ScriptManager* manager() const = 0;
virtual bool maybeEmitUncaughtException(const QString& debugHint = QString()) = 0;
@ -126,6 +126,7 @@ public:
virtual int uncaughtExceptionLineNumber() const = 0;
virtual void updateMemoryCost(const qint64& deltaSize) = 0;
virtual void requestCollectGarbage() = 0;
virtual void compileTest() = 0;
public:
// helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways

View file

@ -826,6 +826,8 @@ void ScriptManager::run() {
// (because we're a client script)
hifi::scripting::setLocalAccessSafeThread(true);
}
_engine->compileTest();
_engine->enterIsolateOnThisThread();

View file

@ -134,7 +134,7 @@ ScriptValue ScriptEngineV8::makeError(const ScriptValue& _other, const QString&
}
// check syntax and when there are issues returns an actual "SyntaxError" with the details
ScriptValue ScriptEngineV8::cheskScriptSyntax(ScriptProgramPointer program) {
ScriptValue ScriptEngineV8::checkScriptSyntax(ScriptProgramPointer program) {
if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {
return nullValue();
}
@ -375,10 +375,13 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
//_arrayBufferClass(new ArrayBufferClass(this))
{
_v8InitMutex.lock();
std::call_once ( _v8InitOnceFlag, [ ]{
std::call_once ( _v8InitOnceFlag, [ ]{
v8::V8::InitializeExternalStartupData("");
//V8TODO might cause crashes if it's too much
v8::V8::SetFlagsFromString("--stack-size=900000");
v8::Platform* platform = getV8Platform();
v8::V8::InitializePlatform(platform);
v8::V8::Initialize();
v8::V8::Initialize(); qCDebug(scriptengine) << "V8 platform initialized";
} );
_v8InitMutex.unlock();
{
@ -391,7 +394,8 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
Q_ASSERT(!context.IsEmpty());
v8::Context::Scope contextScope(context);
_v8Context = v8::UniquePersistent<v8::Context>(_v8Isolate, context);
V8ScriptValue nullScriptValue(_v8Isolate, v8::Null(_v8Isolate));
_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, nullScriptValue));
@ -427,7 +431,7 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
}
}, Qt::DirectConnection);*/
//moveToThread(scriptManager->thread());
setThread(scriptManager->thread());
//setThread(scriptManager->thread());
}
}
@ -789,6 +793,7 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
}
// Compile and check syntax
// V8TODO: Could these all be replaced with checkSyntax function from wrapper?
Q_ASSERT(!_v8Isolate->IsDead());
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
v8::TryCatch tryCatch(getIsolate());
@ -799,7 +804,8 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
int errorLineNumber = 0;
QString errorMessage = "";
QString errorBacktrace = "";
v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception());
//v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception());
v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Message()->Get());
errorMessage = QString(*utf8Value);
v8::Local<v8::Message> exceptionMessage = tryCatch.Message();
if (!exceptionMessage.IsEmpty()) {
@ -811,12 +817,14 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
v8::String::Utf8Value backtraceUtf8Value(getIsolate(), backtraceV8String);
errorBacktrace = *backtraceUtf8Value;
}
qCDebug(scriptengine) << "Compiling script \"" << fileName << "\" failed on line " << errorLineNumber << " column " << errorColumnNumber << " with message: \"" << errorMessage <<"\" backtrace: " << errorBacktrace;
}
auto err = makeError(newValue(errorMessage));
raiseException(err);
maybeEmitUncaughtException("compile");
return err;
}
qCDebug(scriptengine) << "Script compilation succesful: " << fileName;
//V8TODO
/*auto syntaxError = lintScript(sourceCode, fileName);
@ -1170,16 +1178,20 @@ QThread* ScriptEngineV8::thread() const {
}
void ScriptEngineV8::setThread(QThread* thread) {
qDebug() << "Moved script engine " << objectName() << " to different thread";
_v8Isolate->Exit();
if (_v8Isolate->IsCurrent()) {
_v8Isolate->Exit();
qDebug() << "Script engine " << objectName() << " exited isolate";
}
moveToThread(thread);
QMetaObject::invokeMethod(this, "enterIsolateOnThisThread");
qDebug() << "Moved script engine " << objectName() << " to different thread";
}
void ScriptEngineV8::enterIsolateOnThisThread() {
Q_ASSERT(thread() == QThread::currentThread());
_v8Isolate->Enter();
qDebug() << "Script engine " << objectName() << " entered isolate on a new thread";
if (!_v8Isolate->IsCurrent()) {
_v8Isolate->Enter();
qDebug() << "Script engine " << objectName() << " entered isolate on a new thread";
}
}
@ -1238,3 +1250,18 @@ QVariant ScriptEngineV8::convert(const ScriptValue& value, int typeId) {
return var;
return QVariant();
}
void ScriptEngineV8::compileTest() {
v8::Locker locker(_v8Isolate);
v8::Isolate::Scope isolateScope(_v8Isolate);
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
v8::Local<v8::Script> script;
v8::ScriptOrigin scriptOrigin(getIsolate(), v8::String::NewFromUtf8(getIsolate(),"test").ToLocalChecked());
if (v8::Script::Compile(getContext(), v8::String::NewFromUtf8(getIsolate(), "print(\"hello world\");").ToLocalChecked(), &scriptOrigin).ToLocal(&script)) {
qCDebug(scriptengine) << "Compile test succesful";
} else {
qCDebug(scriptengine) << "Compile test failed";
Q_ASSERT(false);
}
}

View file

@ -73,7 +73,7 @@ public: // ScriptEngine implementation
virtual bool hasUncaughtException() const override;
virtual bool isEvaluating() const override;
//virtual ScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1) override;
virtual ScriptValue cheskScriptSyntax(ScriptProgramPointer program) override;
virtual ScriptValue checkScriptSyntax(ScriptProgramPointer program) override;
virtual ScriptValue makeError(const ScriptValue& other, const QString& type = "Error") override;
virtual ScriptManager* manager() const override;
@ -126,6 +126,7 @@ public: // ScriptEngine implementation
virtual int uncaughtExceptionLineNumber() const override;
virtual void updateMemoryCost(const qint64& deltaSize) override;
virtual void requestCollectGarbage() override { while(!_v8Isolate->IdleNotificationDeadline(getV8Platform()->MonotonicallyIncreasingTime() + GARBAGE_COLLECTION_TIME_LIMIT_S)) {}; }
virtual void compileTest() override;
// helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways
inline bool IS_THREADSAFE_INVOCATION(const QString& method) { return ScriptEngine::IS_THREADSAFE_INVOCATION(method); }

View file

@ -44,10 +44,12 @@ bool ScriptProgramV8Wrapper::compile() {
v8::ScriptOrigin scriptOrigin(isolate, v8::String::NewFromUtf8(isolate, _url.toStdString().c_str()).ToLocalChecked());
v8::Local<v8::Script> script;
if (v8::Script::Compile(context, v8::String::NewFromUtf8(isolate, _source.toStdString().c_str()).ToLocalChecked(), &scriptOrigin).ToLocal(&script)) {
qDebug() << "Script compilation succesful: " << _url;
_compileResult = ScriptSyntaxCheckResultV8Wrapper(ScriptSyntaxCheckResult::Valid);
_value = V8ScriptProgram(isolate, script);
return true;
}
qDebug() << "Script compilation failed: " << _url;
v8::String::Utf8Value utf8Value(isolate, tryCatch.Exception());
errorMessage = QString(*utf8Value);
v8::Local<v8::Message> exceptionMessage = tryCatch.Message();

View file

@ -76,15 +76,20 @@ void ScriptEngineTests::scriptTest() {
QVERIFY(!ac.isNull());
ac->loadOneScript("test-missing.js");
ac->loadOneScript("test-hello.js");
ac->loadOneScript("test-divide-by-zero.js");
ac->loadOneScript("test1.js");
//ac->loadOneScript("test-missing.js");
//ac->loadOneScript("test-hello.js");
//ac->loadOneScript("test-divide-by-zero.js");
qDebug() << ac->getRunning();
QSignalSpy spy(ac.get(), SIGNAL(scriptCountChanged));
spy.wait(5000);
ac->shutdownScripting();
while (true) {
QSignalSpy spy(ac.get(), SIGNAL(scriptCountChanged));
spy.wait(3000000);
qDebug() << "Signal happened";
}
//spy.wait(5000);
//ac->shutdownScripting();
}

View file

@ -0,0 +1,26 @@
//
// AudioTests.h
// tests/audio/src
//
// Created by Dale Glass on 27/8/2022
// Copyright 2022 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef overte_ScriptingEngineTests_h
#define overte_ScriptingEngineTests_h
#include <QtTest/QtTest>
class ScriptEngineTests : public QObject {
Q_OBJECT
private slots:
void initTestCase();
void scriptTest();
};
#endif // overte_ScriptingEngineTests_h