From 827ddf595879e7cc53e61322ad684f4e1248f930 Mon Sep 17 00:00:00 2001 From: ksuprynowicz Date: Sat, 15 Oct 2022 12:38:51 +0200 Subject: [PATCH] Added simple compile test function --- libraries/script-engine/src/ScriptEngine.h | 3 +- libraries/script-engine/src/ScriptManager.cpp | 2 + .../script-engine/src/v8/ScriptEngineV8.cpp | 49 ++++++++++++++----- .../script-engine/src/v8/ScriptEngineV8.h | 3 +- .../src/v8/ScriptProgramV8Wrapper.cpp | 2 + tests/script-engine/src/ScriptEngineTests.cpp | 17 ++++--- tests/script-engine/src/ScriptEngineTests.h | 26 ++++++++++ 7 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 tests/script-engine/src/ScriptEngineTests.h diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index a668cb262e..e4b3cb873c 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -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 diff --git a/libraries/script-engine/src/ScriptManager.cpp b/libraries/script-engine/src/ScriptManager.cpp index 81fb31bdce..9f5eb13943 100644 --- a/libraries/script-engine/src/ScriptManager.cpp +++ b/libraries/script-engine/src/ScriptManager.cpp @@ -826,6 +826,8 @@ void ScriptManager::run() { // (because we're a client script) hifi::scripting::setLocalAccessSafeThread(true); } + + _engine->compileTest(); _engine->enterIsolateOnThisThread(); diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.cpp b/libraries/script-engine/src/v8/ScriptEngineV8.cpp index 514c59d8c3..a25038fc40 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8.cpp @@ -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(_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 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 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); + } +} diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.h b/libraries/script-engine/src/v8/ScriptEngineV8.h index 383cdf0afb..6a1cfad5b8 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.h +++ b/libraries/script-engine/src/v8/ScriptEngineV8.h @@ -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); } diff --git a/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.cpp index 6ec8165b6a..54ea3f6723 100644 --- a/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.cpp @@ -44,10 +44,12 @@ bool ScriptProgramV8Wrapper::compile() { v8::ScriptOrigin scriptOrigin(isolate, v8::String::NewFromUtf8(isolate, _url.toStdString().c_str()).ToLocalChecked()); v8::Local 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 exceptionMessage = tryCatch.Message(); diff --git a/tests/script-engine/src/ScriptEngineTests.cpp b/tests/script-engine/src/ScriptEngineTests.cpp index 7c70bf8da5..8907954266 100644 --- a/tests/script-engine/src/ScriptEngineTests.cpp +++ b/tests/script-engine/src/ScriptEngineTests.cpp @@ -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(); } diff --git a/tests/script-engine/src/ScriptEngineTests.h b/tests/script-engine/src/ScriptEngineTests.h new file mode 100644 index 0000000000..f47ef36730 --- /dev/null +++ b/tests/script-engine/src/ScriptEngineTests.h @@ -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 + + + +class ScriptEngineTests : public QObject { + Q_OBJECT +private slots: + void initTestCase(); + void scriptTest(); +}; + +#endif // overte_ScriptingEngineTests_h