V8 fixes, including calls and signals

This commit is contained in:
ksuprynowicz 2023-01-23 00:08:49 +01:00
parent c8898e8366
commit 5099e68b56
11 changed files with 73 additions and 19 deletions

View file

@ -642,7 +642,7 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove
ScriptEnginePointer scriptEngine = newScriptEngine();
ScriptValue props = variantMapToScriptValue(overlayProps, *scriptEngine);
qDebug() << "Overlay props: " << scriptEngine->scriptValueDebugDetails(props);
//qDebug() << "Overlay props: " << scriptEngine->scriptValueDebugDetails(props);
EntityItemProperties toReturn;
EntityItemPropertiesFromScriptValueHonorReadOnly(props, toReturn);
return toReturn;

View file

@ -188,6 +188,7 @@ ScriptValue vec3ColorToScriptValue(ScriptEngine* engine, const glm::vec3& vec3)
return value;
}
// V8TODO: add similar checks to rest of the conversions
bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) {
if (object.isNumber()) {
vec3 = glm::vec3(object.toVariant().toFloat());
@ -197,6 +198,8 @@ bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) {
vec3.x = qColor.red();
vec3.y = qColor.green();
vec3.z = qColor.blue();
} else {
return false;
}
} else if (object.isArray()) {
QVariantList list = object.toVariant().toList();
@ -204,8 +207,10 @@ bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) {
vec3.x = list[0].toFloat();
vec3.y = list[1].toFloat();
vec3.z = list[2].toFloat();
} else {
return false;
}
} else {
} else if (object.isObject()) {
ScriptValue x = object.property("x");
if (!x.isValid()) {
x = object.property("r");
@ -230,9 +235,15 @@ bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) {
z = object.property("blue");
}
if (!x.isValid() || !y.isValid() || !z.isValid()) {
return false;
}
vec3.x = x.toVariant().toFloat();
vec3.y = y.toVariant().toFloat();
vec3.z = z.toVariant().toFloat();
} else {
return false;
}
return true;
}
@ -446,7 +457,18 @@ ScriptValue quatToScriptValue(ScriptEngine* engine, const glm::quat& quat) {
return obj;
}
// V8TODO: add similar check to other conversions
bool quatFromScriptValue(const ScriptValue& object, glm::quat& quat) {
if (!object.isObject()) {
return false;
}
QVariant x = object.property("x").toVariant();
QVariant y = object.property("y").toVariant();
QVariant z = object.property("z").toVariant();
QVariant w = object.property("w").toVariant();
if (!x.isValid() || !y.isValid() || !z.isValid() || !w.isValid()) {
return false;
}
quat.x = object.property("x").toVariant().toFloat();
quat.y = object.property("y").toVariant().toFloat();
quat.z = object.property("z").toVariant().toFloat();

View file

@ -99,10 +99,10 @@ QStringList ScriptContextV8Wrapper::backtrace() const {
for (int i = 0; i < stackTrace->GetFrameCount(); i++) {
v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(isolate, i);
backTrace.append(QString(*v8::String::Utf8Value(isolate, stackFrame->GetScriptNameOrSourceURL())) +
QString(" ") +
QString(*v8::String::Utf8Value(isolate, stackFrame->GetFunctionName())) +
QString(":") +
QString(stackFrame->GetLineNumber())
QString(" ") +
QString(*v8::String::Utf8Value(isolate, stackFrame->GetFunctionName())) +
QString(":") +
QStringLiteral("%1").arg(stackFrame->GetLineNumber())
);
}
return backTrace;

View file

@ -1185,6 +1185,9 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro
raiseException(errorValue);
maybeEmitUncaughtException("evaluate");
hasFailed = true;
} else {
// V8TODO this is just to check if run will always return false for uncaught exception
Q_ASSERT(!tryCatchRun.HasCaught());
}
}
if(!hasFailed) {

View file

@ -182,6 +182,7 @@ public: // not for public use, but I don't like how Qt strings this along with p
v8::Isolate* getIsolate() {return _v8Isolate;}
v8::Local<v8::Context> getContext();
const v8::Local<v8::Context> getConstContext() const;
QString formatErrorMessageFromTryCatch(v8::TryCatch &tryCatch);
// Useful for debugging
//QStringList getCurrentStackTrace();
@ -207,7 +208,6 @@ protected:
static QMutex _v8InitMutex;
static std::once_flag _v8InitOnceFlag;
static v8::Platform* getV8Platform();
QString formatErrorMessageFromTryCatch(v8::TryCatch &tryCatch);
ScriptContextV8Pointer pushContext(v8::Local<v8::Context> &context);
void popContext();

View file

@ -816,7 +816,7 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume
QByteArray argTypeName = _engine->valueType(V8ScriptValue(isolate, argVal)).toLatin1();
QString errorMessage = QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4")
.arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName);
qDebug(scriptengine) << errorMessage;
qDebug(scriptengine) << errorMessage << "\n Backtrace:" << _engine->currentContext()->backtrace();
isolate->ThrowError(v8::String::NewFromUtf8(isolate, errorMessage.toStdString().c_str()).ToLocalChecked());
//context->throwError(V8ScriptContext::TypeError, QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4")
// .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName));
@ -1042,13 +1042,18 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu
Connection& conn = *iter;
v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(conn.callback.get());
v8::Local<v8::Value> v8This;
if (conn.thisValue.get()->IsNull()) {
v8This = _engine->getContext()->Global();
} else {
if (conn.thisValue.get()->IsObject()) {
v8This = conn.thisValue.get();
} else {
v8This = _engine->getContext()->Global();
}
//V8TODO: should there be a trycatch here?
v8::TryCatch tryCatch(isolate);
callback->Call(_engine->getContext(), v8This, numArgs, args);
if (tryCatch.HasCaught()) {
qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \""
<< _engine->formatErrorMessageFromTryCatch(tryCatch) << "This: " << conn.thisValue.get()->IsObject();
}
}
return -1;

View file

@ -71,7 +71,8 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
auto context = _engine->getContext();
v8::Context::Scope contextScope(context);
V8ScriptValue v8This = fullUnwrap(thisObject);
//V8ScriptValueList qArgs;
Q_ASSERT(args.length() <= Q_METAMETHOD_INVOKE_MAX_ARGS);
@ -81,10 +82,23 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
for (ScriptValueList::const_iterator iter = args.begin(); iter != args.end(); ++iter) {
v8Args[argIndex++] = fullUnwrap(*iter).get();
}
//V8TODO should there be a v8 try-catch here?
// IsFunction check should be here probably
// V8TODO: IsFunction check should be here probably
v8::Local<v8::Function> v8Function = v8::Local<v8::Function>::Cast(_value.get());
auto maybeResult = v8Function->Call(_engine->getContext(), v8This.get(), args.length(), v8Args);
v8::TryCatch tryCatch(isolate);
v8::Local<v8::Value> recv;
if (v8This.get()->IsObject()) {
recv = v8This.get();
//qDebug() << "V8 This: " << _engine->scriptValueDebugDetailsV8(v8This);
}else{
recv = _engine->getContext()->Global();
//qDebug() << "global";
}
//qDebug() << "V8 Call: " << *v8::String::Utf8Value(isolate, v8This.get()->TypeOf(isolate));
auto maybeResult = v8Function->Call(_engine->getContext(), recv, args.length(), v8Args);
// V8TODO: Exceptions don't seem to actually be caught here?
if (tryCatch.HasCaught()) {
qCDebug(scriptengine) << "Function call failed: \"" << _engine->formatErrorMessageFromTryCatch(tryCatch);
}
v8::Local<v8::Value> result;
if (maybeResult.ToLocal(&result)) {
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result)));
@ -262,7 +276,11 @@ ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValu
qDebug() << "Failed to get property, parent of value: " << name << ", parent type: " << QString(*v8::String::Utf8Value(isolate, _value.constGet()->TypeOf(isolate))) << " parent value: " << parentValueQString;
}
}
if (name == QString("x")) {
printf("x");
}
qDebug() << "Failed to get property, parent of value: " << name << " is not a V8 object, reported type: " << QString(*v8::String::Utf8Value(isolate, _value.constGet()->TypeOf(isolate)));
qDebug() << "Backtrace: " << _engine->currentContext()->backtrace();
return _engine->undefinedValue();
/*v8::Local<v8::Value> nullValue = v8::Null(_engine->getIsolate());
V8ScriptValue nullScriptValue(_engine->getIsolate(), std::move(nullValue));

View file

@ -106,6 +106,10 @@ Script.include("/~/system/libraries/utils.js");
this.sendPointingAtData = function(controllerData) {
var rayPick = controllerData.rayPicks[this.hand];
var hudRayPick = controllerData.hudRayPicks[this.hand];
// V8TODO: this needs to be checked if it works correctly
if (!hudRayPick.intersects) {
return;
}
var point2d = this.calculateNewReticlePosition(hudRayPick.intersection);
var desktopWindow = Window.isPointOnDesktopWindow(point2d);
var tablet = this.pointingAtTablet(rayPick.objectID);

View file

@ -1682,8 +1682,8 @@ Script.scriptEnding.connect(function () {
createButton = null;
});
var lastOrientation = null;
var lastPosition = null;
var lastOrientation = Camera.orientation;
var lastPosition = Camera.position;
// Do some stuff regularly, like check for placement of various overlays
Script.update.connect(function (deltaTime) {

View file

@ -297,6 +297,7 @@ var EntityListTool = function(shouldUseEditTabletApp) {
}
var onWebEventReceived = function(data) {
print("entityList.js onWebEventReceived: " + data);
try {
data = JSON.parse(data);
} catch(e) {

View file

@ -7,7 +7,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// Interface Metadata Source
var INTERFACE_METADATA_SOURCE = "https://cdn.vircadia.com/dist/launcher/vircadiaMeta.json";
//var INTERFACE_METADATA_SOURCE = "https://cdn.vircadia.com/dist/launcher/vircadiaMeta.json";
var INTERFACE_METADATA_SOURCE = "";
// Base CDN URLs
var CONTENT_CDN_URL = Script.getExternalPath(Script.ExternalPaths.HF_Content, "/");