diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 3326cdcf45..5656c93333 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -60,7 +60,7 @@ jobs: # Do not change the names of self-hosted runners without knowing what you are doing, as they correspond to labels that have to be set on the runner. - os: self-hosted_debian-11_aarch64 build_type: full - apt-dependencies: qtbase5-dev qtbase5-private-dev qtwebengine5-dev qtwebengine5-dev-tools qtmultimedia5-dev libqt5opengl5-dev qtscript5-dev libqt5scripttools5 libqt5webchannel5-dev libqt5websockets5-dev qtxmlpatterns5-dev-tools qttools5-dev libqt5xmlpatterns5-dev libqt5svg5-dev qml-module-qtwebchannel build-essential cmake curl freeglut3-dev git libasound2 libasound2-dev libdouble-conversion-dev libdrm-dev libfontconfig1 libgl1-mesa-dev libglvnd-dev libharfbuzz-dev libjack-dev libjack0 libnspr4 libnss3 libpcre2-16-0 libpulse0 libsdl2-dev libssl-dev libudev-dev libxcb-xinerama0-dev libxcb-xinput0 libxcomposite1 libxcursor1 libxi-dev libxmu-dev libxrandr-dev libxslt1.1 libxtst6 make mesa-common-dev mesa-utils nodejs npm patchelf python2 python3 python3-distro xdg-user-dirs zlib1g-dev ninja-build zip python3-distro + apt-dependencies: qtbase5-dev qtbase5-private-dev qtwebengine5-dev qtwebengine5-dev-tools qtmultimedia5-dev libqt5opengl5-dev libqt5webchannel5-dev libqt5websockets5-dev qtxmlpatterns5-dev-tools qttools5-dev libqt5xmlpatterns5-dev libqt5svg5-dev qml-module-qtwebchannel build-essential cmake curl freeglut3-dev git libasound2 libasound2-dev libdouble-conversion-dev libdrm-dev libfontconfig1 libgl1-mesa-dev libglvnd-dev libharfbuzz-dev libjack-dev libjack0 libnspr4 libnss3 libpcre2-16-0 libpulse0 libsdl2-dev libssl-dev libudev-dev libxcb-xinerama0-dev libxcb-xinput0 libxcomposite1 libxcursor1 libxi-dev libxmu-dev libxrandr-dev libxslt1.1 libxtst6 make mesa-common-dev mesa-utils nodejs npm patchelf python2 python3 python3-distro xdg-user-dirs zlib1g-dev ninja-build zip python3-distro fail-fast: false runs-on: ${{matrix.os}} steps: diff --git a/libraries/script-engine-qtscript/src/BaseScriptEngine.h b/libraries/script-engine-qtscript/src/BaseScriptEngine.h index 1835a06d82..0851321888 100644 --- a/libraries/script-engine-qtscript/src/BaseScriptEngine.h +++ b/libraries/script-engine-qtscript/src/BaseScriptEngine.h @@ -12,7 +12,7 @@ #ifndef hifi_BaseScriptEngine_h #define hifi_BaseScriptEngine_h -#include +/*#include #include #include #include @@ -29,23 +29,23 @@ public: BaseScriptEngine() {} - /*@jsdoc + *@jsdoc * @function Script.lintScript * @param {string} sourceCode - Source code. * @param {string} fileName - File name. * @param {number} [lineNumber=1] - Line number. * @returns {object} Object. * @deprecated This function is deprecated and will be removed. - */ + * Q_INVOKABLE QScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1); - /*@jsdoc + *@jsdoc * @function Script.makeError * @param {object} [other] - Other. * @param {string} [type="Error"] - Error. * @returns {object} Object. * @deprecated This function is deprecated and will be removed. - */ + * Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error"); QScriptValue cloneUncaughtException(const QString& detail = QString()); @@ -61,12 +61,12 @@ public: // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways static bool IS_THREADSAFE_INVOCATION(const QThread *thread, const QString& method); signals: - /*@jsdoc + *@jsdoc * @function Script.signalHandlerException * @param {object} exception - Exception. * @returns {Signal} * @deprecated This signal is deprecated and will be removed. - */ + * // Script.signalHandlerException is exposed by QScriptEngine. protected: @@ -95,6 +95,6 @@ private: QScriptEngine* engine; std::function operation; QScriptValue data; -}; +};*/ #endif // hifi_BaseScriptEngine_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 4bcac85e45..e1879f4aed 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -14,10 +14,10 @@ #include "ScriptEngineLogging.h" #include "ScriptValue.h" -#include "qtscript/ScriptEngineQtScript.h" +#include "v8/ScriptEngineV8.h" ScriptEnginePointer newScriptEngine(ScriptManager* manager) { - return std::make_shared(manager); + return std::make_shared(manager); } ScriptValue makeScopedHandlerObject(const ScriptValue& scopeOrCallback, const ScriptValue& methodOrName) { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 9708babf83..c2628f9317 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -78,16 +78,23 @@ public: virtual ScriptValue evaluate(const QString& program, const QString& fileName = QString()) = 0; virtual ScriptValue evaluate(const ScriptProgramPointer &program) = 0; virtual ScriptValue evaluateInClosure(const ScriptValue& locals, const ScriptProgramPointer& program) = 0; - virtual ScriptValue globalObject() const = 0; + virtual ScriptValue globalObject() const { + Q_ASSERT(false); + return ScriptValue(); + } 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 lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1) = 0; + virtual ScriptValue cheskScriptSyntax(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; virtual ScriptValue newArray(uint length = 0) = 0; virtual ScriptValue newArrayBuffer(const QByteArray& message) = 0; - virtual ScriptValue newFunction(FunctionSignature fun, int length = 0) = 0; + virtual ScriptValue newFunction(FunctionSignature fun, int length = 0) { + Q_ASSERT(false); + return ScriptValue(); + } virtual ScriptValue newObject() = 0; virtual ScriptProgramPointer newProgram(const QString& sourceCode, const QString& fileName) = 0; virtual ScriptValue newQObject(QObject *object, ValueOwnership ownership = QtOwnership, const QObjectWrapOptions &options = QObjectWrapOptions()) = 0; diff --git a/libraries/script-engine/src/ScriptManager.cpp b/libraries/script-engine/src/ScriptManager.cpp index ad68b63002..c19b942075 100644 --- a/libraries/script-engine/src/ScriptManager.cpp +++ b/libraries/script-engine/src/ScriptManager.cpp @@ -53,6 +53,7 @@ #include "ScriptEngines.h" #include "StackTestScriptingInterface.h" #include "ScriptValue.h" +#include "ScriptProgram.h" #include "ScriptValueIterator.h" #include "ScriptValueUtils.h" @@ -1935,18 +1936,21 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c } // SYNTAX ERRORS - auto syntaxError = _engine->lintScript(contents, fileName); - if (syntaxError.isError()) { - auto message = syntaxError.property("formatted").toString(); - if (message.isEmpty()) { - message = syntaxError.toString(); - } + //auto syntaxError = _engine->lintScript(contents, fileName); + auto program = _engine->newProgram( contents, fileName ); + auto syntaxCheck = program->checkSyntax(); + if (syntaxCheck->state() != ScriptSyntaxCheckResult::Valid) { + auto message = syntaxCheck->errorMessage(); + //syntaxError.property("formatted").toString(); + //if (message.isEmpty()) { + // message = syntaxError.toString(); + //} setError(QString("Bad syntax (%1)").arg(message), EntityScriptStatus::ERROR_RUNNING_SCRIPT); - syntaxError.setProperty("detail", entityID.toString()); - emit unhandledException(syntaxError); + //syntaxError.setProperty("detail", entityID.toString()); + //V8TODO + //emit unhandledException(syntaxError); return; } - auto program = _engine->newProgram( contents, fileName ); if (!program) { setError("Bad program (isNull)", EntityScriptStatus::ERROR_RUNNING_SCRIPT); emit unhandledException(_engine->makeError(_engine->newValue("program.isNull"))); diff --git a/libraries/script-engine/src/ScriptManager.h b/libraries/script-engine/src/ScriptManager.h index fe78fcd517..db65e9fdfd 100644 --- a/libraries/script-engine/src/ScriptManager.h +++ b/libraries/script-engine/src/ScriptManager.h @@ -889,7 +889,7 @@ signals: void releaseEntityPacketSenderMessages(bool wait); protected: - // Is called by the constructor, bceause all types need to be registered before method discovery with ScriptObjectQtProxy::investigate() + // Is called by the constructor, bceause all types need to be registered before method discovery with ScriptObjectV8Proxy::investigate() void initMetaTypes(); void init(); diff --git a/libraries/script-engine/src/ScriptProgram.h b/libraries/script-engine/src/ScriptProgram.h index ae26abace6..3392595432 100644 --- a/libraries/script-engine/src/ScriptProgram.h +++ b/libraries/script-engine/src/ScriptProgram.h @@ -25,7 +25,7 @@ using ScriptSyntaxCheckResultPointer = std::shared_ptr; /// [ScriptInterface] Provides an engine-independent interface for QScriptProgram class ScriptProgram { public: - virtual ScriptSyntaxCheckResultPointer checkSyntax() const = 0; + virtual ScriptSyntaxCheckResultPointer checkSyntax() = 0; //It cannot be const anymore because V8 doesn't have separate syntax checking function virtual QString fileName() const = 0; virtual QString sourceCode() const = 0; @@ -47,6 +47,7 @@ public: virtual int errorColumnNumber() const = 0; virtual int errorLineNumber() const = 0; virtual QString errorMessage() const = 0; + virtual QString errorBacktrace() const = 0; virtual State state() const = 0; protected: diff --git a/libraries/script-engine/src/ScriptValue.h b/libraries/script-engine/src/ScriptValue.h index 40334733bc..4f2d5725fd 100644 --- a/libraries/script-engine/src/ScriptValue.h +++ b/libraries/script-engine/src/ScriptValue.h @@ -50,10 +50,12 @@ public: SkipInEnumeration = 0x00000004, PropertyGetter = 0x00000008, PropertySetter = 0x00000010, + QObjectMember = 0x00000020, KeepExistingFlags = 0x00000800, }; Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag); + public: ScriptValue(); inline ScriptValue(const ScriptValue& src); @@ -112,6 +114,8 @@ public: inline QObject* toQObject() const; protected: + //V8TODO + //Won't a regular pointer cause memory leak? ScriptValueProxy* _proxy; }; Q_DECLARE_OPERATORS_FOR_FLAGS(ScriptValue::PropertyFlags); diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.cpp b/libraries/script-engine/src/v8/ScriptEngineV8.cpp index a8d7b73c98..ca87bc4b11 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8.cpp @@ -475,16 +475,16 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) #ifdef THREAD_DEBUGGING qCDebug(scriptengine) << "ScriptEngineV8::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name; #endif*/ - v8::Local globalObject = getContext()->Global(); + v8::Local v8GlobalObject = getContext()->Global(); v8::Local v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); // V8TODO: Is IsEmpty check enough or IsValid is needed too? - if (!globalObject->Get(getContext(), v8Name).IsEmpty()) { + if (!v8GlobalObject->Get(getContext(), v8Name).IsEmpty()) { if (object) { V8ScriptValue value = ScriptObjectV8Proxy::newQObject(this, object, ScriptEngine::QtOwnership); - globalObject->Set(getContext(), v8Name, value.get()); + v8GlobalObject->Set(getContext(), v8Name, value.get()); } else { - globalObject->Set(getContext(), v8Name, v8::Null(_v8Isolate)); + v8GlobalObject->Set(getContext(), v8Name, v8::Null(_v8Isolate)); } } } @@ -1018,9 +1018,9 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int } //V8TODO -/*void ScriptEngineV8::setObjectName(const QString& name) { - QScriptEngine::setObjectName(name); -}*/ +void ScriptEngineV8::setObjectName(const QString& name) { + QObject::setObjectName(name); +} //V8TODO bool ScriptEngineV8::setProperty(const char* name, const QVariant& value) { diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.h b/libraries/script-engine/src/v8/ScriptEngineV8.h index c9bd7a80b4..675d1380a3 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.h +++ b/libraries/script-engine/src/v8/ScriptEngineV8.h @@ -50,7 +50,7 @@ const double GARBAGE_COLLECTION_TIME_LIMIT_S = 1.0; Q_DECLARE_METATYPE(ScriptEngine::FunctionSignature) /// [V8] Implements ScriptEngine for V8 and translates calls for QScriptEngine -class ScriptEngineV8 final : public ScriptEngine, +class ScriptEngineV8 final : public QObject, public ScriptEngine, public std::enable_shared_from_this { Q_OBJECT @@ -115,7 +115,7 @@ public: // ScriptEngine implementation Q_INVOKABLE virtual void registerGlobalObject(const QString& name, QObject* object) override; virtual void setDefaultPrototype(int metaTypeId, const ScriptValue& prototype) override; // Already implemented by QObject - //virtual void setObjectName(const QString& name) override; + virtual void setObjectName(const QString& name) override; virtual bool setProperty(const char* name, const QVariant& value) override; virtual void setProcessEventsInterval(int interval) override; virtual QThread* thread() const override;