mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Further work on evaluateInClosure
This commit is contained in:
parent
70d4a43009
commit
ed968e1ebd
5 changed files with 63 additions and 10 deletions
|
@ -127,7 +127,7 @@ public:
|
|||
virtual void updateMemoryCost(const qint64& deltaSize) = 0;
|
||||
virtual void requestCollectGarbage() = 0;
|
||||
virtual void compileTest() = 0;
|
||||
virtual QString scriptValueDebugDetails(ScriptValue &value) = 0;
|
||||
virtual QString scriptValueDebugDetails(const ScriptValue &value) = 0;
|
||||
|
||||
public:
|
||||
// helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways
|
||||
|
|
|
@ -1422,6 +1422,7 @@ ScriptValue ScriptManager::instantiateModule(const ScriptValue& module, const QS
|
|||
closure.setProperty("require", module.property("require"));
|
||||
closure.setProperty("__filename", modulePath, READONLY_HIDDEN_PROP_FLAGS);
|
||||
closure.setProperty("__dirname", QString(modulePath).replace(QRegExp("/[^/]*$"), ""), READONLY_HIDDEN_PROP_FLAGS);
|
||||
_engine->scriptValueDebugDetails(module);
|
||||
result = _engine->evaluateInClosure(closure, _engine->newProgram( sourceCode, modulePath ));
|
||||
}
|
||||
_engine->maybeEmitUncaughtException(__FUNCTION__);
|
||||
|
|
|
@ -800,20 +800,24 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
Q_ASSERT(false);
|
||||
return nullValue();
|
||||
}
|
||||
//qDebug() << "Closure global details:" << scriptValueDebugDetailsV8(V8ScriptValue(_v8Isolate, closureGlobal));
|
||||
}
|
||||
//_v8Context.Get(_v8Isolate)->DetachGlobal();
|
||||
//oldGlobal = _v8Context.Get(_v8Isolate)->Global();
|
||||
v8::Local<v8::Context> closureContext;
|
||||
|
||||
if (closureGlobal->IsObject()) {
|
||||
// V8TODO
|
||||
/*if (closureGlobal->IsObject()) {
|
||||
#ifdef DEBUG_JS
|
||||
qCDebug(shared) << " setting global = closure.global" << shortName;
|
||||
#endif
|
||||
closureContext = v8::Context::New(_v8Isolate, nullptr, v8::Local<v8::ObjectTemplate>(), closureGlobal);
|
||||
closureContext = v8::Context::New(_v8Isolate, nullptr, v8::Local<v8::ObjectTemplate>(), closureGlobal);
|
||||
//setGlobalObject(global);
|
||||
} else {
|
||||
closureContext = v8::Context::New(_v8Isolate);
|
||||
}
|
||||
}*/
|
||||
closureContext = v8::Context::New(_v8Isolate, nullptr, v8::Local<v8::ObjectTemplate>(), closureObject);
|
||||
|
||||
ScriptValue result;
|
||||
//auto context = pushContext();
|
||||
|
@ -828,23 +832,25 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
const V8ScriptProgram& program = unwrappedProgram->toV8Value();
|
||||
|
||||
v8::Local<v8::Value> thiz;
|
||||
// V8TODO: not sure if "this" doesn't exist or is empty in some cases
|
||||
if (!closureObject->Get(closure.constGetContext(), v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked())
|
||||
// V8TODO: not sure if "this" is used at all here
|
||||
/*if (!closureObject->Get(closure.constGetContext(), v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked())
|
||||
.ToLocal(&thiz)) {
|
||||
_evaluatingCounter--;
|
||||
qDebug(scriptengine) << "Empty this object in closure";
|
||||
Q_ASSERT(false);
|
||||
return nullValue();
|
||||
}
|
||||
}*/
|
||||
//thiz = closure.property("this");
|
||||
if (thiz->IsObject()) {
|
||||
//qDebug() << "Closure this details:" << scriptValueDebugDetailsV8(V8ScriptValue(_v8Isolate, thiz));
|
||||
// V8TODO:
|
||||
/*if (thiz->IsObject()) {
|
||||
#ifdef DEBUG_JS
|
||||
qCDebug(shared) << " setting this = closure.this" << shortName;
|
||||
#endif
|
||||
//V8TODO I don't know how to do this in V8, will adding "this" to global object work?
|
||||
closureContext->Global()->Set(closureContext, v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked(), thiz);
|
||||
//context->setThisObject(thiz);
|
||||
}
|
||||
}*/
|
||||
|
||||
//context->pushScope(closure);
|
||||
#ifdef DEBUG_JS
|
||||
|
@ -852,12 +858,15 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
#endif
|
||||
{
|
||||
v8::TryCatch tryCatch(getIsolate());
|
||||
//qDebug(scriptengine) << "Closure before run:" << scriptValueDebugDetailsV8(closure);
|
||||
auto maybeResult = program.constGet()->Run(closureContext);
|
||||
//qDebug(scriptengine) << "Closure after run:" << scriptValueDebugDetailsV8(closure);
|
||||
v8::Local<v8::Value> v8Result;
|
||||
if (!maybeResult.ToLocal(&v8Result)) {
|
||||
v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception());
|
||||
QString errorMessage = QString(*utf8Value);
|
||||
qWarning(scriptengine) << __FUNCTION__ << "---------- hasCaught:" << errorMessage;
|
||||
qWarning(scriptengine) << __FUNCTION__ << "---------- tryCatch details:" << formatErrorMessageFromTryCatch(tryCatch);
|
||||
//V8TODO: better error reporting
|
||||
}
|
||||
|
||||
|
@ -1513,7 +1522,7 @@ void ScriptEngineV8::compileTest() {
|
|||
}
|
||||
}
|
||||
|
||||
QString ScriptEngineV8::scriptValueDebugDetails(ScriptValue &value) {
|
||||
QString ScriptEngineV8::scriptValueDebugDetails(const ScriptValue &value) {
|
||||
V8ScriptValue v8Value = ScriptValueV8Wrapper::fullUnwrap(this, value);
|
||||
return scriptValueDebugDetailsV8(v8Value);
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ public: // ScriptEngine implementation
|
|||
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;
|
||||
virtual QString scriptValueDebugDetails(ScriptValue &value) override;
|
||||
virtual QString scriptValueDebugDetails(const ScriptValue &value) override;
|
||||
QString scriptValueDebugDetailsV8(const V8ScriptValue &value);
|
||||
|
||||
// helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways
|
||||
|
@ -171,6 +171,9 @@ public: // not for public use, but I don't like how Qt strings this along with p
|
|||
ScriptEngine::DemarshalFunction demarshalFunc) override;
|
||||
int computeCastPenalty(const V8ScriptValue& val, int destTypeId);
|
||||
bool castValueToVariant(const V8ScriptValue& val, QVariant& dest, int destTypeId);
|
||||
|
||||
// Converts JS objects created in V8 to variants. Iterates over all properties and converts them to variants.
|
||||
bool convertJSObjectToVariant(v8::Local<v8::Object> object, QVariant &dest);
|
||||
V8ScriptValue castVariantToValue(const QVariant& val);
|
||||
QString valueType(const V8ScriptValue& val);
|
||||
v8::Isolate* getIsolate() {return _v8Isolate;}
|
||||
|
|
|
@ -383,6 +383,12 @@ bool ScriptEngineV8::castValueToVariant(const V8ScriptValue& v8Val, QVariant& de
|
|||
break;
|
||||
}
|
||||
}
|
||||
// This is for generic JS objects
|
||||
if (val->IsObject()) {
|
||||
if (convertJSObjectToVariant(v8::Local<v8::Object>::Cast(val), dest)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// V8TODO
|
||||
errorMessage = QString() + "Conversion failure: " + QString(*v8::String::Utf8Value(_v8Isolate, val->ToDetailString(getConstContext()).ToLocalChecked()))
|
||||
+ "to variant. Destination type: " + QMetaType::typeName(destTypeId) +" details: "+ scriptValueDebugDetailsV8(v8Val);
|
||||
|
@ -487,6 +493,12 @@ bool ScriptEngineV8::castValueToVariant(const V8ScriptValue& v8Val, QVariant& de
|
|||
return true;
|
||||
}
|
||||
}
|
||||
if (val->IsObject()) {
|
||||
if (convertJSObjectToVariant(v8::Local<v8::Object>::Cast(val), dest)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//V8TODO is v8::Array to QVariant conversion used anywhere?
|
||||
errorMessage = QString() + "Conversion to variant failed: " + QString(*v8::String::Utf8Value(_v8Isolate, val->ToDetailString(getConstContext()).ToLocalChecked()))
|
||||
+ " Destination type: " + QMetaType::typeName(destTypeId) + " Value details: " + scriptValueDebugDetailsV8(v8Val);
|
||||
qDebug() << errorMessage;
|
||||
|
@ -532,6 +544,34 @@ bool ScriptEngineV8::castValueToVariant(const V8ScriptValue& v8Val, QVariant& de
|
|||
return destTypeId == QMetaType::UnknownType || dest.userType() == destTypeId || dest.convert(destTypeId);
|
||||
}
|
||||
|
||||
bool ScriptEngineV8::convertJSObjectToVariant(v8::Local<v8::Object> object, QVariant &dest) {
|
||||
auto context = getContext();
|
||||
v8::Local<v8::Array> names;
|
||||
if(object->GetPropertyNames(context).ToLocal(&names)) {
|
||||
qDebug() << "ScriptEngineV8::convertJSObjectToVariant could not get property names";
|
||||
return false;
|
||||
}
|
||||
int length = names->Length();
|
||||
QHash<QString, QVariant> properties;
|
||||
for (int i = 0; i < length; i++) {
|
||||
v8::Local<v8::Value> v8Property;
|
||||
QString name = *v8::String::Utf8Value(_v8Isolate, names->Get(context, i).ToLocalChecked());
|
||||
if (!object->Get(context, names->Get(context, i).ToLocalChecked()).ToLocal(&v8Property)) {
|
||||
qDebug() << "ScriptEngineV8::convertJSObjectToVariant could not get property: " + name;
|
||||
continue;
|
||||
}
|
||||
QVariant property;
|
||||
// Maybe QMetaType::QVariant?
|
||||
if (castValueToVariant(V8ScriptValue(_v8Isolate, v8Property), property, QMetaType::UnknownType)) {
|
||||
properties.insert( name, property);
|
||||
} else {
|
||||
qDebug() << "ScriptEngineV8::convertJSObjectToVariant could cast property to variant: " + name;
|
||||
;
|
||||
}
|
||||
}
|
||||
dest = QVariant(properties);
|
||||
}
|
||||
|
||||
QString ScriptEngineV8::valueType(const V8ScriptValue& v8Val) {
|
||||
// V8TODO
|
||||
v8::HandleScope handleScope(const_cast<v8::Isolate*>(v8Val.constGetIsolate()));
|
||||
|
|
Loading…
Reference in a new issue