From f65e72c8f2653754e2060ce0ed2d416b3083d085 Mon Sep 17 00:00:00 2001 From: ksuprynowicz Date: Tue, 14 Feb 2023 23:48:31 +0100 Subject: [PATCH] Listing objects and their properties on API debugger now works --- .../PlatformInfoScriptingInterface.h | 7 +- .../script-engine/src/ScriptValueUtils.cpp | 38 +++++++++++ .../script-engine/src/ScriptValueUtils.h | 8 +++ .../src/v8/ScriptEngineV8_cast.cpp | 4 +- .../src/v8/ScriptObjectV8Proxy.cpp | 66 +++++++++++++++++-- .../src/v8/ScriptObjectV8Proxy.h | 2 + .../developer/utilities/tools/currentAPI.js | 1 + 7 files changed, 118 insertions(+), 8 deletions(-) diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.h b/interface/src/scripting/PlatformInfoScriptingInterface.h index 767b776e8c..f13ecb0724 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.h +++ b/interface/src/scripting/PlatformInfoScriptingInterface.h @@ -25,8 +25,12 @@ class PlatformInfoScriptingInterface : public QObject { Q_OBJECT +private: + static PlatformInfoScriptingInterface* getInstance(); + friend class Application; public: + PlatformInfoScriptingInterface(); virtual ~PlatformInfoScriptingInterface(); @@ -55,11 +59,10 @@ public: Q_ENUM(PlatformTier); public slots: - /*@jsdoc + /* * @function PlatformInfo.getInstance * @deprecated This function is deprecated and will be removed. */ - static PlatformInfoScriptingInterface* getInstance(); /*@jsdoc * Gets the operating system type. diff --git a/libraries/script-engine/src/ScriptValueUtils.cpp b/libraries/script-engine/src/ScriptValueUtils.cpp index e28f87245c..1b5024bb0f 100644 --- a/libraries/script-engine/src/ScriptValueUtils.cpp +++ b/libraries/script-engine/src/ScriptValueUtils.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include #include @@ -52,6 +54,9 @@ bool isListOfStrings(const ScriptValue& arg) { } void registerMetaTypes(ScriptEngine* engine) { + scriptRegisterMetaType(engine); + scriptRegisterMetaType(engine); + scriptRegisterMetaType(engine); scriptRegisterMetaType(engine); scriptRegisterMetaType(engine); @@ -93,6 +98,39 @@ void registerMetaTypes(ScriptEngine* engine) { scriptRegisterSequenceMetaType>(engine); } +ScriptValue qVector2DToScriptValue(ScriptEngine* engine, const QVector2D& qVector2D) { + glm::vec2 vec2(qVector2D.x(), qVector2D.y()); + return vec2ToScriptValue(engine, vec2); +} + +bool qVector2DFromScriptValue(const ScriptValue& object, QVector2D& qVector2D) { + glm::vec2 vec2; + if (vec2FromScriptValue(object, vec2)) { + qVector2D.setX(vec2.x); + qVector2D.setY(vec2.y); + return true; + } else { + return false; + } +} + +ScriptValue qVector3DToScriptValue(ScriptEngine* engine, const QVector3D& qVector3D) { + glm::vec3 vec3(qVector3D.x(), qVector3D.y(), qVector3D.z()); + return vec3ToScriptValue(engine, vec3); +} + +bool qVector3DFromScriptValue(const ScriptValue& object, QVector3D& qVector3D) { + glm::vec3 vec3; + if (vec3FromScriptValue(object, vec3)) { + qVector3D.setX(vec3.x); + qVector3D.setY(vec3.y); + qVector3D.setZ(vec3.z); + return true; + } else { + return false; + } +} + ScriptValue vec2ToScriptValue(ScriptEngine* engine, const glm::vec2& vec2) { auto prototype = engine->globalObject().property("__hifi_vec2__"); if (!prototype.property("defined").toBool()) { diff --git a/libraries/script-engine/src/ScriptValueUtils.h b/libraries/script-engine/src/ScriptValueUtils.h index 57d4691def..c2faa9c279 100644 --- a/libraries/script-engine/src/ScriptValueUtils.h +++ b/libraries/script-engine/src/ScriptValueUtils.h @@ -161,6 +161,14 @@ bool quatFromScriptValue(const ScriptValue& object, glm::quat& quat); * @property {number} width - Width of the rectangle. * @property {number} height - Height of the rectangle. */ +class QVector2D; +ScriptValue qVector2DToScriptValue(ScriptEngine* engine, const QVector2D& qVector2D); +bool qVector2DFromScriptValue(const ScriptValue& object, QVector2D& qVector2D); + +class QVector3D; +ScriptValue qVector3DToScriptValue(ScriptEngine* engine, const QVector3D& qVector3D); +bool qVector3DFromScriptValue(const ScriptValue& object, QVector3D& qVector3D); + class QRect; ScriptValue qRectToScriptValue(ScriptEngine* engine, const QRect& rect); bool qRectFromScriptValue(const ScriptValue& object, QRect& rect); diff --git a/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp b/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp index b614a063fe..45d0e244c2 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp @@ -769,7 +769,9 @@ V8ScriptValue ScriptEngineV8::castVariantToValue(const QVariant& val) { } // just do a generic variant //V8TODO - Q_ASSERT(false); + qDebug() << "ScriptEngineV8::castVariantToValue failed for " << QMetaType::typeName(valTypeId); + logBacktrace("ScriptEngineV8::castVariantToValue failed"); + //Q_ASSERT(false); return V8ScriptValue(this, v8::Undefined(_v8Isolate)); //return QScriptEngine::newVariant(val); } diff --git a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp index c4b3a0a030..43f0cc42b5 100644 --- a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp +++ b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp @@ -225,14 +225,11 @@ void ScriptObjectV8Proxy::investigate() { //auto objectTemplate = _v8ObjectTemplate.Get(_engine->getIsolate()); auto objectTemplate = v8::ObjectTemplate::New(_engine->getIsolate()); objectTemplate->SetInternalFieldCount(3); - objectTemplate->SetHandler(v8::NamedPropertyHandlerConfiguration(v8Get, v8Set)); + objectTemplate->SetHandler(v8::NamedPropertyHandlerConfiguration(v8Get, v8Set, nullptr, nullptr, v8GetPropertyNames)); const QMetaObject* metaObject = qobject->metaObject(); //qDebug(scriptengine) << "Investigate: " << metaObject->className(); - if (QString("Vec3") == metaObject->className()) { - printf("Vec3"); - } if (QString("ConsoleScriptingInterface") == metaObject->className()) { printf("ConsoleScriptingInterface"); } @@ -494,6 +491,60 @@ void ScriptObjectV8Proxy::v8Set(v8::Local name, v8::Local v } } +void ScriptObjectV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo& info) { + qDebug(scriptengine) << "ScriptObjectV8Proxy::v8GetPropertyNames called"; + v8::HandleScope handleScope(info.GetIsolate()); + auto context = info.GetIsolate()->GetCurrentContext(); + v8::Context::Scope contextScope(context); + v8::Local objectV8 = info.This(); + ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8); + if (!proxy) { + qDebug(scriptengine) << "ScriptObjectV8Proxy::v8GetPropertyNames: Proxy object not found when listing"; + return; + } + V8ScriptValue object(proxy->_engine, objectV8); + uint id; + v8::Local properties = proxy->getPropertyNames(); + v8::Local objectProperties; + uint32_t propertiesLength = properties->Length(); + if (info.This()->GetInternalField(2).As()->GetPropertyNames(context).ToLocal(&objectProperties)) { + for (int n = 0; n < objectProperties->Length(); n++) { + if(!properties->Set(context, propertiesLength+n, objectProperties->Get(context, n).ToLocalChecked()).FromMaybe(false)) { + qDebug(scriptengine) << "ScriptObjectV8Proxy::v8GetPropertyNames: Cannot add member name"; + } + } + } + info.GetReturnValue().Set(properties); +} + +v8::Local ScriptObjectV8Proxy::getPropertyNames() { + auto isolate = _engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::EscapableHandleScope handleScope(_engine->getIsolate()); + auto context = _engine->getContext(); + v8::Context::Scope contextScope(_engine->getContext()); + + v8::Local properties = v8::Array::New(isolate, _props.size() + _methods.size() + _signals.size()); + uint32_t position = 0; + for (PropertyDefMap::const_iterator i = _props.begin(); i != _props.end(); i++){ + if(!properties->Set(context, position++, i.value().name.constGet()).FromMaybe(false)) { + qDebug(scriptengine) << "ScriptObjectV8Proxy::getPropertyNames: Cannot add property member name"; + } + } + for (MethodDefMap::const_iterator i = _methods.begin(); i != _methods.end(); i++){ + if(!properties->Set(context, position++, i.value().name.constGet()).FromMaybe(false)) { + qDebug(scriptengine) << "ScriptObjectV8Proxy::getPropertyNames: Cannot add property member name"; + } + } + for (SignalDefMap::const_iterator i = _signals.begin(); i != _signals.end(); i++){ + if(!properties->Set(context, position++, i.value().name.constGet()).FromMaybe(false)) { + qDebug(scriptengine) << "ScriptObjectV8Proxy::getPropertyNames: Cannot add property member name"; + } + } + return handleScope.Escape(properties); +} + V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V8ScriptString& name, uint id) { auto isolate = _engine->getIsolate(); @@ -840,7 +891,12 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo& argume // The Qt MOC engine will automatically call qRegisterMetaType on invokable parameters and properties, but there's // nothing in there for return values so these need to be explicitly runtime-registered! - Q_ASSERT(returnTypeId != QMetaType::UnknownType); + if (returnTypeId == QMetaType::UnknownType) { + QString methodName = fullName(); + qDebug(scriptengine) << "returnTypeId == QMetaType::UnknownType for method " << methodName; + _engine->logBacktrace(""); + //Q_ASSERT(false); + } if (returnTypeId == QMetaType::UnknownType) { isolate->ThrowError(v8::String::NewFromUtf8(isolate, QString("Cannot call native function %1, its return value has not been registered with Qt").arg(fullName()).toStdString().c_str()).ToLocalChecked()); return; diff --git a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.h b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.h index 94893ed3a2..d65e507ff2 100644 --- a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.h +++ b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.h @@ -97,8 +97,10 @@ public: //V8TODO virtual QueryFlags queryProperty(const V8ScriptValue& object, const V8ScriptString& name, QueryFlags flags, uint* id); virtual void setProperty(V8ScriptValue& object, const V8ScriptString& name, uint id, const V8ScriptValue& value); + v8::Local getPropertyNames(); static void v8Get(v8::Local name, const v8::PropertyCallbackInfo& info); static void v8Set(v8::Local name, v8::Local value_obj, const v8::PropertyCallbackInfo& info); + static void v8GetPropertyNames(const v8::PropertyCallbackInfo& info); private: // implementation void investigate(); diff --git a/scripts/developer/utilities/tools/currentAPI.js b/scripts/developer/utilities/tools/currentAPI.js index 6cab6a5710..190a5939e2 100644 --- a/scripts/developer/utilities/tools/currentAPI.js +++ b/scripts/developer/utilities/tools/currentAPI.js @@ -90,6 +90,7 @@ var keys = Object.keys(object); for (var i = 0; i < keys.length; ++i) { + print("key: " + keys[i]); if (string === "") { listKeys(keys[i], object[keys[i]]); } else if (keys[i] !== "parent") {