mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 07:12:40 +02:00
Added context scopes
This commit is contained in:
parent
2b06c09318
commit
a4c6930a50
10 changed files with 300 additions and 95 deletions
|
@ -7506,8 +7506,9 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptManage
|
|||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||
LocationScriptingInterface::locationSetter, "Window");
|
||||
// register `location` on the global object.
|
||||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||
LocationScriptingInterface::locationSetter);
|
||||
//V8TODO causes a crash
|
||||
//scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||
// LocationScriptingInterface::locationSetter);
|
||||
|
||||
scriptEngine->registerFunction("OverlayWindow", clientScript ? QmlWindowClass::constructor : QmlWindowClass::restricted_constructor);
|
||||
#if !defined(Q_OS_ANDROID) && !defined(DISABLE_QML)
|
||||
|
|
|
@ -119,6 +119,7 @@ public:
|
|||
virtual void setProcessEventsInterval(int interval) = 0;
|
||||
virtual QThread* thread() const = 0;
|
||||
virtual void setThread(QThread* thread) = 0;
|
||||
Q_INVOKABLE virtual void enterIsolateOnThisThread() = 0;
|
||||
virtual ScriptValue undefinedValue() = 0;
|
||||
virtual ScriptValue uncaughtException() const = 0;
|
||||
virtual QStringList uncaughtExceptionBacktrace() const = 0;
|
||||
|
|
|
@ -825,7 +825,9 @@ void ScriptManager::run() {
|
|||
// (because we're a client script)
|
||||
hifi::scripting::setLocalAccessSafeThread(true);
|
||||
}
|
||||
|
||||
|
||||
_engine->enterIsolateOnThisThread();
|
||||
|
||||
auto filenameParts = _fileNameString.split("/");
|
||||
auto name = filenameParts.size() > 0 ? filenameParts[filenameParts.size() - 1] : "unknown";
|
||||
PROFILE_SET_THREAD_NAME("Script: " + name);
|
||||
|
|
|
@ -38,12 +38,23 @@ v8::Local<v8::Context> ScriptContextV8Wrapper::toV8Value() const {
|
|||
}
|
||||
|
||||
int ScriptContextV8Wrapper::argumentCount() const {
|
||||
Q_ASSERT(_functionCallbackInfo);
|
||||
return _functionCallbackInfo->Length();
|
||||
/*auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());*/
|
||||
//Q_ASSERT(_functionCallbackInfo);A
|
||||
// V8TODO
|
||||
return Q_METAMETHOD_INVOKE_MAX_ARGS;
|
||||
// This was wrong, in function registration it seems to be used as maximum number od arguments instead?
|
||||
// Is it also used for something else?
|
||||
//return _functionCallbackInfo->Length();
|
||||
}
|
||||
|
||||
ScriptValue ScriptContextV8Wrapper::argument(int index) const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
Q_ASSERT(_functionCallbackInfo);
|
||||
v8::Local<v8::Value> result = (*_functionCallbackInfo)[index];
|
||||
//V8ScriptValue result = _context->argument(index);
|
||||
|
@ -52,7 +63,9 @@ ScriptValue ScriptContextV8Wrapper::argument(int index) const {
|
|||
|
||||
QStringList ScriptContextV8Wrapper::backtrace() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 40);
|
||||
QStringList backTrace;
|
||||
//V8TODO nicer formatting
|
||||
|
@ -93,20 +106,29 @@ ScriptContextPointer ScriptContextV8Wrapper::parentContext() const {
|
|||
|
||||
ScriptValue ScriptContextV8Wrapper::thisObject() const {
|
||||
Q_ASSERT(_functionCallbackInfo);
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Local<v8::Value> result = _functionCallbackInfo->This();
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result)));
|
||||
return ScriptValue();
|
||||
}
|
||||
|
||||
ScriptValue ScriptContextV8Wrapper::throwError(const QString& text) {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
V8ScriptValue result(_engine->getIsolate(), _engine->getIsolate()->ThrowError(v8::String::NewFromUtf8(_engine->getIsolate(), text.toStdString().c_str()).ToLocalChecked()));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptValue ScriptContextV8Wrapper::throwValue(const ScriptValue& value) {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(value);
|
||||
if (!unwrapped) {
|
||||
return _engine->undefinedValue();
|
||||
|
|
|
@ -113,6 +113,8 @@ ScriptValue ScriptEngineV8::makeError(const ScriptValue& _other, const QString&
|
|||
if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {
|
||||
return nullValue();
|
||||
}
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
return nullValue();
|
||||
|
||||
//V8TODO
|
||||
|
@ -136,6 +138,8 @@ ScriptValue ScriptEngineV8::cheskScriptSyntax(ScriptProgramPointer program) {
|
|||
if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {
|
||||
return nullValue();
|
||||
}
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
ScriptSyntaxCheckResultPointer syntaxCheck = program->checkSyntax();
|
||||
//V8TODO
|
||||
if (syntaxCheck->state() != ScriptSyntaxCheckResult::Valid) {
|
||||
|
@ -190,6 +194,8 @@ ScriptValue ScriptEngineV8::cloneUncaughtException(const QString& extraDetail) {
|
|||
if (!hasUncaughtException()) {
|
||||
return nullValue();
|
||||
}
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
return nullValue();
|
||||
//V8TODO
|
||||
/*
|
||||
|
@ -284,6 +290,8 @@ bool ScriptEngineV8::maybeEmitUncaughtException(const QString& debugHint) {
|
|||
ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8ScriptContext*, ScriptEngineV8*)> operation,
|
||||
const V8ScriptValue& data,
|
||||
const ValueOwnership& ownership) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
auto lambda = new Lambda(this, operation, data);
|
||||
auto object = newQObject(lambda, ownership);
|
||||
//V8TODO?
|
||||
|
@ -294,6 +302,7 @@ ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8Scri
|
|||
}
|
||||
QString Lambda::toString() const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Local<v8::String> string;
|
||||
QString qString("");
|
||||
if (_data.constGet()->ToString(_engine->getContext()).ToLocal(&string)) {
|
||||
|
@ -373,30 +382,14 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
|
|||
v8::Isolate::CreateParams isolateParams;
|
||||
isolateParams.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
|
||||
_v8Isolate = v8::Isolate::New(isolateParams);
|
||||
_v8Isolate->Enter();
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Local<v8::Context> context = v8::Context::New(_v8Isolate);
|
||||
Q_ASSERT(!context.IsEmpty());
|
||||
_v8Context = v8::UniquePersistent<v8::Context>(_v8Isolate, context);
|
||||
|
||||
registerSystemTypes();
|
||||
|
||||
_currentThread = QThread::currentThread();
|
||||
// V8TODO: port to V8
|
||||
/*
|
||||
if (_scriptManager) {
|
||||
connect(this, &QScriptEngine::signalHandlerException, this, [this](const V8ScriptValue& exception) {
|
||||
if (hasUncaughtException()) {
|
||||
// the engine's uncaughtException() seems to produce much better stack traces here
|
||||
emit _scriptManager->unhandledException(cloneUncaughtException("signalHandlerException"));
|
||||
clearExceptions();
|
||||
} else {
|
||||
// ... but may not always be available -- so if needed we fallback to the passed exception
|
||||
V8ScriptValue thrown = makeError(exception);
|
||||
emit _scriptManager->unhandledException(ScriptValue(new ScriptValueV8Wrapper(this, std::move(thrown))));
|
||||
}
|
||||
}, Qt::DirectConnection);
|
||||
moveToThread(scriptManager->thread());
|
||||
}*/
|
||||
|
||||
// V8TODO: dispose of isolate on ScriptEngineV8 destruction
|
||||
//v8::UniquePersistent<v8::Value> null = v8::UniquePersistent<v8::Value>(_v8Isolate, v8::Null(_v8Isolate));
|
||||
//_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(null)));
|
||||
|
@ -410,6 +403,25 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
|
|||
|
||||
// V8TODO:
|
||||
//QScriptEngine::setProcessEventsInterval(MSECS_PER_SECOND);
|
||||
|
||||
//_currentThread = QThread::currentThread();
|
||||
|
||||
if (_scriptManager) {
|
||||
// V8TODO: port to V8
|
||||
/*connect(this, &QScriptEngine::signalHandlerException, this, [this](const V8ScriptValue& exception) {
|
||||
if (hasUncaughtException()) {
|
||||
// the engine's uncaughtException() seems to produce much better stack traces here
|
||||
emit _scriptManager->unhandledException(cloneUncaughtException("signalHandlerException"));
|
||||
clearExceptions();
|
||||
} else {
|
||||
// ... but may not always be available -- so if needed we fallback to the passed exception
|
||||
V8ScriptValue thrown = makeError(exception);
|
||||
emit _scriptManager->unhandledException(ScriptValue(new ScriptValueV8Wrapper(this, std::move(thrown))));
|
||||
}
|
||||
}, Qt::DirectConnection);*/
|
||||
//moveToThread(scriptManager->thread());
|
||||
setThread(scriptManager->thread());
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngineV8::registerEnum(const QString& enumName, QMetaEnum newEnum) {
|
||||
|
@ -417,6 +429,8 @@ void ScriptEngineV8::registerEnum(const QString& enumName, QMetaEnum newEnum) {
|
|||
qCCritical(scriptengine) << "registerEnum called on invalid enum with name " << enumName;
|
||||
return;
|
||||
}
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
|
||||
for (int i = 0; i < newEnum.keyCount(); i++) {
|
||||
const char* keyName = newEnum.key(i);
|
||||
|
@ -426,8 +440,7 @@ void ScriptEngineV8::registerEnum(const QString& enumName, QMetaEnum newEnum) {
|
|||
}
|
||||
|
||||
void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value) {
|
||||
//V8TODO
|
||||
/*if (QThread::currentThread() != QScriptEngine::thread()) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerValue() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]";
|
||||
#endif
|
||||
|
@ -435,8 +448,9 @@ void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value
|
|||
Q_ARG(const QString&, valueName),
|
||||
Q_ARG(V8ScriptValue, value));
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
QStringList pathToValue = valueName.split(".");
|
||||
int partsToGo = pathToValue.length();
|
||||
v8::Local<v8::Object> partObject = _v8Context.Get(_v8Isolate)->Global();
|
||||
|
@ -470,8 +484,7 @@ void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value
|
|||
}
|
||||
|
||||
void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) {
|
||||
//V8TODO
|
||||
/*if (QThread::currentThread() != QScriptEngine::thread()) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerGlobalObject() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;
|
||||
#endif
|
||||
|
@ -482,8 +495,10 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object)
|
|||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "ScriptEngineV8::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name;
|
||||
#endif*/
|
||||
#endif
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
Q_ASSERT(_v8Isolate->IsCurrent());
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
v8::Local<v8::Object> v8GlobalObject = getContext()->Global();
|
||||
v8::Local<v8::String> v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked();
|
||||
|
||||
|
@ -499,22 +514,23 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object)
|
|||
}
|
||||
|
||||
void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) {
|
||||
//V8TODO
|
||||
/*if (QThread::currentThread() != QScriptEngine::thread()) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;
|
||||
#endif
|
||||
QMetaObject::invokeMethod(this, "registerFunction",
|
||||
Q_ARG(const QString&, name),
|
||||
Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
|
||||
Q_ARG(ScriptEngine::FunctionSignature, functionSignature),
|
||||
Q_ARG(int, numArguments));
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name;
|
||||
#endif*/
|
||||
#endif
|
||||
|
||||
//auto scriptFun = static_cast<ScriptValueV8Wrapper*>(newFunction(functionSignature, numArguments).ptr())->toV8Value().constGet();
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
auto scriptFun = newFunction(functionSignature, numArguments);
|
||||
|
||||
//getContext()->Global().Set();
|
||||
|
@ -522,21 +538,22 @@ void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::Functio
|
|||
}
|
||||
|
||||
void ScriptEngineV8::registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) {
|
||||
//V8TODO
|
||||
/*if (QThread::currentThread() != QScriptEngine::thread()) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] parent:" << parent << "name:" << name;
|
||||
#endif
|
||||
QMetaObject::invokeMethod(this, "registerFunction",
|
||||
Q_ARG(const QString&, name),
|
||||
Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
|
||||
Q_ARG(ScriptEngine::FunctionSignature, functionSignature),
|
||||
Q_ARG(int, numArguments));
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name;
|
||||
#endif*/
|
||||
#endif
|
||||
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
ScriptValue object = globalObject().property(parent);
|
||||
if (object.isValid()) {
|
||||
ScriptValue scriptFun = ScriptEngine::newFunction(functionSignature, numArguments);
|
||||
|
@ -546,8 +563,7 @@ void ScriptEngineV8::registerFunction(const QString& parent, const QString& name
|
|||
|
||||
void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter,
|
||||
ScriptEngine::FunctionSignature setter, const QString& parent) {
|
||||
//V8TODO
|
||||
/*if (QThread::currentThread() != QScriptEngine::thread()) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerGetterSetter() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
||||
" name:" << name << "parent:" << parent;
|
||||
|
@ -561,7 +577,10 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun
|
|||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "ScriptEngineV8::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent;
|
||||
#endif*/
|
||||
#endif
|
||||
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
|
||||
ScriptValue setterFunction = newFunction(setter, 1);
|
||||
ScriptValue getterFunction = newFunction(getter);
|
||||
|
@ -585,6 +604,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
return nullValue();
|
||||
}
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
ScriptProgramV8Wrapper* unwrappedProgram = ScriptProgramV8Wrapper::unwrap(_program);
|
||||
if (unwrappedProgram == nullptr) {
|
||||
return nullValue();
|
||||
|
@ -684,7 +704,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
setGlobalObject(oldGlobal);
|
||||
}*/
|
||||
|
||||
_v8Context.Get(_v8Isolate)->Enter();
|
||||
//_v8Context.Get(_v8Isolate)->Enter();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -695,7 +715,7 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
|
|||
|
||||
//V8TODO
|
||||
|
||||
/*if (QThread::currentThread() != QScriptEngine::thread()) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
ScriptValue result;
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
||||
|
@ -706,10 +726,11 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
|
|||
Q_ARG(const QString&, sourceCode),
|
||||
Q_ARG(const QString&, fileName));
|
||||
return result;
|
||||
}*/
|
||||
}
|
||||
// Compile and check syntax
|
||||
// V8TODO: Could these all be replaced with checkSyntax function from wrapper?
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
v8::TryCatch tryCatch(getIsolate());
|
||||
v8::ScriptOrigin scriptOrigin(getIsolate(), v8::String::NewFromUtf8(getIsolate(), fileName.toStdString().c_str()).ToLocalChecked());
|
||||
v8::Local<v8::Script> script;
|
||||
|
@ -775,8 +796,7 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro
|
|||
return undefinedValue(); // bail early
|
||||
}
|
||||
|
||||
//V8TODO
|
||||
/*if (QThread::currentThread() != QScriptEngine::thread()) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
ScriptValue result;
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
||||
|
@ -786,8 +806,9 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro
|
|||
Q_RETURN_ARG(ScriptValue, result),
|
||||
Q_ARG(const ScriptProgramPointer&, program));
|
||||
return result;
|
||||
}*/
|
||||
}
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
ScriptProgramV8Wrapper* unwrapped = ScriptProgramV8Wrapper::unwrap(program);
|
||||
if (!unwrapped) {
|
||||
auto err = makeError(newValue("could not unwrap program"));
|
||||
|
@ -843,6 +864,7 @@ void ScriptEngineV8::updateMemoryCost(const qint64& deltaSize) {
|
|||
|
||||
ScriptValue ScriptEngineV8::globalObject() const {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue global(_v8Isolate, getConstContext()->Global());// = QScriptEngine::globalObject(); // can't cache the value as it may change
|
||||
return ScriptValue(new ScriptValueV8Wrapper(const_cast<ScriptEngineV8*>(this), std::move(global)));
|
||||
}
|
||||
|
@ -852,12 +874,15 @@ ScriptManager* ScriptEngineV8::manager() const {
|
|||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newArray(uint length) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue result(_v8Isolate, v8::Array::New(_v8Isolate, static_cast<int>(length)));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
//V8TODO: this will leak memory
|
||||
std::shared_ptr<v8::BackingStore> backingStore(v8::ArrayBuffer::NewBackingStore(_v8Isolate, message.size()));
|
||||
std::memcpy(backingStore.get()->Data(), message.constData(), message.size());
|
||||
|
@ -873,12 +898,16 @@ ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) {
|
|||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newObject() {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue result(_v8Isolate, v8::Object::New(_v8Isolate));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newMethod(QObject* object, V8ScriptValue lifetime,
|
||||
const QList<QMetaMethod>& metas, int numMaxParams) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue result(ScriptMethodV8Proxy::newMethod(this, object, lifetime, metas, numMaxParams));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
@ -893,33 +922,43 @@ ScriptProgramPointer ScriptEngineV8::newProgram(const QString& sourceCode, const
|
|||
ScriptValue ScriptEngineV8::newQObject(QObject* object,
|
||||
ScriptEngine::ValueOwnership ownership,
|
||||
const ScriptEngine::QObjectWrapOptions& options) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue result = ScriptObjectV8Proxy::newQObject(this, object, ownership, options);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newValue(bool value) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue result(_v8Isolate, v8::Boolean::New(_v8Isolate, value));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newValue(int value) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue result(_v8Isolate, v8::Integer::New(_v8Isolate, value));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newValue(uint value) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue result(_v8Isolate, v8::Uint32::New(_v8Isolate, value));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newValue(double value) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue result(_v8Isolate, v8::Number::New(_v8Isolate, value));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newValue(const QString& value) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value.toStdString().c_str(), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
V8ScriptValue result(_v8Isolate, valueV8);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
|
@ -927,6 +966,7 @@ ScriptValue ScriptEngineV8::newValue(const QString& value) {
|
|||
|
||||
ScriptValue ScriptEngineV8::newValue(const QLatin1String& value) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value.latin1(), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
V8ScriptValue result(_v8Isolate, valueV8);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
|
@ -934,12 +974,15 @@ ScriptValue ScriptEngineV8::newValue(const QLatin1String& value) {
|
|||
|
||||
ScriptValue ScriptEngineV8::newValue(const char* value) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value, v8::NewStringType::kNormal).ToLocalChecked();
|
||||
V8ScriptValue result(_v8Isolate, valueV8);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::newVariant(const QVariant& value) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
V8ScriptValue result = castVariantToValue(value);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
@ -1005,12 +1048,14 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int
|
|||
//V8TODO: is using GetCurrentContext ok, or context wrapper needs to be added?
|
||||
v8::HandleScope handleScope(info.GetIsolate());
|
||||
auto context = info.GetIsolate()->GetCurrentContext();
|
||||
v8::Context::Scope contextScope(context);
|
||||
auto object = v8::Local<v8::Object>::Cast(info.Data());
|
||||
auto function = reinterpret_cast<ScriptEngine::FunctionSignature>
|
||||
(info.Data()->ToObject(context).ToLocalChecked()->GetAlignedPointerFromInternalField(0));
|
||||
(object->GetAlignedPointerFromInternalField(0));
|
||||
ScriptContext *scriptContext = reinterpret_cast<ScriptContext*>
|
||||
(info.Data()->ToObject(context).ToLocalChecked()->GetAlignedPointerFromInternalField(1));;
|
||||
(object->GetAlignedPointerFromInternalField(1));;
|
||||
ScriptEngineV8 *scriptEngine = reinterpret_cast<ScriptEngineV8*>
|
||||
(info.Data()->ToObject(context).ToLocalChecked()->GetAlignedPointerFromInternalField(2));;
|
||||
(object->GetAlignedPointerFromInternalField(2));;
|
||||
ScriptValue result = function(scriptContext, scriptEngine);
|
||||
ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result);
|
||||
info.GetReturnValue().Set(unwrapped->toV8Value().constGet());
|
||||
|
@ -1019,6 +1064,7 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int
|
|||
//auto functionData = v8::Object::New(_v8Isolate);
|
||||
//functionData->setIn
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
auto functionDataTemplate = v8::ObjectTemplate::New(_v8Isolate);
|
||||
functionDataTemplate->SetInternalFieldCount(3);
|
||||
auto functionData = functionDataTemplate->NewInstance(getContext()).ToLocalChecked();
|
||||
|
@ -1044,6 +1090,7 @@ void ScriptEngineV8::setObjectName(const QString& name) {
|
|||
//V8TODO
|
||||
bool ScriptEngineV8::setProperty(const char* name, const QVariant& value) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
v8::Local<v8::Object> global = getContext()->Global();
|
||||
auto v8Name = v8::String::NewFromUtf8(getIsolate(), name).ToLocalChecked();
|
||||
V8ScriptValue v8Value = castVariantToValue(value);
|
||||
|
@ -1056,13 +1103,23 @@ void ScriptEngineV8::setProcessEventsInterval(int interval) {
|
|||
}
|
||||
|
||||
QThread* ScriptEngineV8::thread() const {
|
||||
return _currentThread;
|
||||
return QObject::thread();
|
||||
}
|
||||
|
||||
void ScriptEngineV8::setThread(QThread* thread) {
|
||||
qDebug() << "Moved script engine " << objectName() << " to different thread";
|
||||
_v8Isolate->Exit();
|
||||
moveToThread(thread);
|
||||
QMetaObject::invokeMethod(this, "enterIsolateOnThisThread");
|
||||
}
|
||||
|
||||
void ScriptEngineV8::enterIsolateOnThisThread() {
|
||||
Q_ASSERT(thread() == QThread::currentThread());
|
||||
_v8Isolate->Enter();
|
||||
qDebug() << "Script engine " << objectName() << " entered isolate on a new thread";
|
||||
}
|
||||
|
||||
|
||||
ScriptValue ScriptEngineV8::uncaughtException() const {
|
||||
//V8TODO
|
||||
//V8ScriptValue result = QScriptEngine::uncaughtException();
|
||||
|
@ -1088,12 +1145,16 @@ bool ScriptEngineV8::raiseException(const ScriptValue& exception) {
|
|||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::create(int type, const void* ptr) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
QVariant variant(type, ptr);
|
||||
V8ScriptValue scriptValue = castVariantToValue(variant);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(scriptValue)));
|
||||
}
|
||||
|
||||
QVariant ScriptEngineV8::convert(const ScriptValue& value, int typeId) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
|
||||
ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(value);
|
||||
if (unwrapped == nullptr) {
|
||||
return QVariant();
|
||||
|
|
|
@ -114,12 +114,12 @@ public: // ScriptEngine implementation
|
|||
const QString& parent = QString("")) override;
|
||||
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 bool setProperty(const char* name, const QVariant& value) override;
|
||||
virtual void setProcessEventsInterval(int interval) override;
|
||||
virtual QThread* thread() const override;
|
||||
virtual void setThread(QThread* thread) override;
|
||||
Q_INVOKABLE virtual void enterIsolateOnThisThread() override;
|
||||
virtual ScriptValue undefinedValue() override;
|
||||
virtual ScriptValue uncaughtException() const override;
|
||||
virtual QStringList uncaughtExceptionBacktrace() const override;
|
||||
|
@ -219,7 +219,7 @@ protected:
|
|||
ScriptValue _nullValue;
|
||||
ScriptValue _undefinedValue;
|
||||
mutable ScriptContextQtPointer _currContext;
|
||||
QThread *_currentThread;
|
||||
//QThread *_currentThread;
|
||||
|
||||
//V8TODO
|
||||
//ArrayBufferClass* _arrayBufferClass;
|
||||
|
|
|
@ -139,7 +139,7 @@ ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val)
|
|||
if (!v8Value->IsObject()) {
|
||||
return nullptr;
|
||||
}
|
||||
v8::Local<v8::Object> v8Object = v8Value->ToObject(val.constGetContext()).ToLocalChecked();
|
||||
v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(v8Value);
|
||||
if (v8Object->InternalFieldCount() != 2) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -167,6 +167,7 @@ void ScriptObjectV8Proxy::investigate() {
|
|||
if (!qobject) return;
|
||||
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
|
||||
auto objectTemplate = _v8ObjectTemplate.Get(_engine->getIsolate());
|
||||
objectTemplate->SetInternalFieldCount(3);
|
||||
|
@ -228,13 +229,17 @@ void ScriptObjectV8Proxy::investigate() {
|
|||
break;
|
||||
}
|
||||
|
||||
V8ScriptString name(_engine->getIsolate(), v8::String::NewFromUtf8(_engine->getIsolate(), szName.data(), v8::NewStringType::kNormal, szName.length()).ToLocalChecked());
|
||||
auto nameString = v8::String::NewFromUtf8(_engine->getIsolate(), szName.data(), v8::NewStringType::kNormal, szName.length()).ToLocalChecked();
|
||||
V8ScriptString name(_engine->getIsolate(), nameString);
|
||||
auto nameLookup = methodNames.find(name);
|
||||
if (isSignal) {
|
||||
if (nameLookup == methodNames.end()) {
|
||||
SignalDef& signalDef = _signals.insert(idx, SignalDef(_engine->getIsolate(), name.get())).value();
|
||||
signalDef.name = name;
|
||||
signalDef.signal = method;
|
||||
qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), nameString));
|
||||
qDebug(scriptengine) << "Utf8Value 2: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), name.constGet()));
|
||||
qDebug(scriptengine) << "toQString: " << name.toQString();
|
||||
methodNames.insert(name, idx);
|
||||
} else {
|
||||
int originalMethodId = nameLookup.value();
|
||||
|
@ -474,7 +479,7 @@ ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val
|
|||
if (!v8Value->IsObject()) {
|
||||
return nullptr;
|
||||
}
|
||||
v8::Local<v8::Object> v8Object = v8Value->ToObject(val.constGetContext()).ToLocalChecked();
|
||||
v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(v8Value);
|
||||
if (v8Object->InternalFieldCount() != 2) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,8 @@ V8ScriptValueIterator::V8ScriptValueIterator(ScriptEngineV8* engine, v8::Local<v
|
|||
v8::HandleScope handleScope(isolate);
|
||||
_context.Reset(isolate, _engine->getContext());
|
||||
auto context = _context.Get(isolate);
|
||||
v8::Local<v8::Object> v8Object;
|
||||
if (!object->ToObject(context).ToLocal(&v8Object)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
Q_ASSERT(object->IsObject());
|
||||
v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(object);
|
||||
_object.Reset(isolate, v8Object);
|
||||
_propertyNames.Reset(isolate, v8Object->GetOwnPropertyNames(context).ToLocalChecked());
|
||||
_length = _propertyNames.Get(isolate)->Length();
|
||||
|
|
|
@ -60,7 +60,10 @@ V8ScriptValue ScriptValueV8Wrapper::fullUnwrap(ScriptEngineV8* engine, const Scr
|
|||
}
|
||||
|
||||
ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const ScriptValueList& args) {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
V8ScriptValue v8This = fullUnwrap(thisObject);
|
||||
//V8ScriptValueList qArgs;
|
||||
Q_ASSERT(args.length() <= Q_METAMETHOD_INVOKE_MAX_ARGS);
|
||||
|
@ -85,7 +88,10 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
|
|||
}
|
||||
|
||||
ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const ScriptValue& arguments) {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
V8ScriptValue v8This = fullUnwrap(thisObject);
|
||||
V8ScriptValue v8Args = fullUnwrap(arguments);
|
||||
// V8TODO should there be a v8 try-catch here?
|
||||
|
@ -106,7 +112,10 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
|
|||
}
|
||||
|
||||
ScriptValue ScriptValueV8Wrapper::construct(const ScriptValueList& args) {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
Q_ASSERT(args.length() <= Q_METAMETHOD_INVOKE_MAX_ARGS);
|
||||
//V8TODO I'm not sure how else to do this since v8::Local should probably be on stack, not heap
|
||||
v8::Local<v8::Value> v8Args[Q_METAMETHOD_INVOKE_MAX_ARGS];
|
||||
|
@ -129,7 +138,10 @@ ScriptValue ScriptValueV8Wrapper::construct(const ScriptValueList& args) {
|
|||
}
|
||||
|
||||
ScriptValue ScriptValueV8Wrapper::construct(const ScriptValue& arguments) {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
// V8TODO I'm not sure in what format arguments are yet, backtrace will show how it is used
|
||||
Q_ASSERT(false);
|
||||
return _engine->undefinedValue();
|
||||
|
@ -157,13 +169,17 @@ ScriptValueIteratorPointer ScriptValueV8Wrapper::newIterator() const {
|
|||
}
|
||||
|
||||
ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValue::ResolveFlags& mode) const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
if (!_value.constGet()->IsObject()) {
|
||||
//V8TODO: what about flags?
|
||||
v8::Local<v8::Value> resultLocal;
|
||||
v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
|
||||
if (_value.constGet()->ToObject(_value.constGetContext()).ToLocalChecked()
|
||||
->Get(_value.constGetContext(), key).ToLocal(&resultLocal)) {
|
||||
v8::Local<v8::Value> resultLocal;
|
||||
v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Q_ASSERT(_value.constGet()->IsObject());
|
||||
const v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(_value.constGet());
|
||||
if (object->Get(_value.constGetContext(), key).ToLocal(&resultLocal)) {
|
||||
V8ScriptValue result(_engine->getIsolate(), resultLocal);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
|
||||
}
|
||||
|
@ -176,12 +192,16 @@ ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValu
|
|||
}
|
||||
|
||||
ScriptValue ScriptValueV8Wrapper::property(quint32 arrayIndex, const ScriptValue::ResolveFlags& mode) const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
if (!_value.constGet()->IsObject()) {
|
||||
//V8TODO: what about flags?
|
||||
v8::Local<v8::Value> resultLocal;
|
||||
if (_value.constGet()->ToObject(_value.constGetContext()).ToLocalChecked()
|
||||
->Get(_value.constGetContext(), arrayIndex).ToLocal(&resultLocal)) {
|
||||
v8::Local<v8::Value> resultLocal;
|
||||
Q_ASSERT(_value.constGet()->IsObject());
|
||||
const v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(_value.constGet());
|
||||
if (object->Get(_value.constGetContext(), arrayIndex).ToLocal(&resultLocal)) {
|
||||
V8ScriptValue result(_engine->getIsolate(), resultLocal);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
|
||||
}
|
||||
|
@ -192,17 +212,28 @@ ScriptValue ScriptValueV8Wrapper::property(quint32 arrayIndex, const ScriptValue
|
|||
}
|
||||
|
||||
void ScriptValueV8Wrapper::setData(const ScriptValue& value) {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
V8ScriptValue unwrapped = fullUnwrap(value);
|
||||
(**_value.get()) = (**unwrapped.get());
|
||||
}
|
||||
|
||||
void ScriptValueV8Wrapper::setProperty(const QString& name, const ScriptValue& value, const ScriptValue::PropertyFlags& flags) {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
V8ScriptValue unwrapped = fullUnwrap(value);
|
||||
if(_value.constGet()->IsObject()) {
|
||||
v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
|
||||
v8::Maybe<bool> retVal = _value.get()->ToObject(_value.getContext()).ToLocalChecked()
|
||||
->Set(_value.getContext(), key, unwrapped.constGet());
|
||||
v8::Local<v8::String> key = v8::String::NewFromUtf8(isolate, name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Q_ASSERT(_value.get()->IsObject());
|
||||
auto object = v8::Local<v8::Object>::Cast(_value.get());
|
||||
// V8TODO: What if velue context and current context is different?
|
||||
//v8::Maybe<bool> retVal = object->Set(_value.getContext(), key, unwrapped.constGet());
|
||||
//v8::Maybe<bool> retVal = object->Set(_engine->getContext(), key, unwrapped.constGet());
|
||||
v8::Maybe<bool> retVal = object->Set(isolate->GetCurrentContext(), key, unwrapped.constGet());
|
||||
if (retVal.IsJust() ? !retVal.FromJust() : true){
|
||||
qDebug(scriptengine) << "Failed to set property";
|
||||
}
|
||||
|
@ -214,10 +245,14 @@ void ScriptValueV8Wrapper::setProperty(const QString& name, const ScriptValue& v
|
|||
}
|
||||
|
||||
void ScriptValueV8Wrapper::setProperty(quint32 arrayIndex, const ScriptValue& value, const ScriptValue::PropertyFlags& flags) {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
V8ScriptValue unwrapped = fullUnwrap(value);
|
||||
if(_value.constGet()->IsObject()) {
|
||||
v8::Maybe<bool> retVal(_value.get()->ToObject(_value.getContext()).ToLocalChecked()
|
||||
->Set(_value.getContext(), arrayIndex, unwrapped.constGet()));
|
||||
auto object = v8::Local<v8::Object>::Cast(_value.get());
|
||||
v8::Maybe<bool> retVal(object->Set(_value.getContext(), arrayIndex, unwrapped.constGet()));
|
||||
if (retVal.IsJust() ? !retVal.FromJust() : true){
|
||||
qDebug(scriptengine) << "Failed to set property";
|
||||
}
|
||||
|
@ -229,11 +264,15 @@ void ScriptValueV8Wrapper::setProperty(quint32 arrayIndex, const ScriptValue& va
|
|||
}
|
||||
|
||||
void ScriptValueV8Wrapper::setPrototype(const ScriptValue& prototype) {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
ScriptValueV8Wrapper* unwrappedPrototype = unwrap(prototype);
|
||||
if (unwrappedPrototype) {
|
||||
if(unwrappedPrototype->toV8Value().constGet()->IsObject() && _value.constGet()->IsObject()) {
|
||||
v8::Maybe<bool> retVal = _value.get()->ToObject(_value.getContext()).ToLocalChecked()
|
||||
->SetPrototype(_value.getContext(), unwrappedPrototype->toV8Value().constGet());
|
||||
auto object = v8::Local<v8::Object>::Cast(_value.get());
|
||||
v8::Maybe<bool> retVal = object->SetPrototype(_value.getContext(), unwrappedPrototype->toV8Value().constGet());
|
||||
if (retVal.IsJust() ? !retVal.FromJust() : true){
|
||||
qDebug(scriptengine) << "Failed to assign prototype";
|
||||
}
|
||||
|
@ -244,18 +283,27 @@ void ScriptValueV8Wrapper::setPrototype(const ScriptValue& prototype) {
|
|||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::strictlyEquals(const ScriptValue& other) const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
ScriptValueV8Wrapper* unwrappedOther = unwrap(other);
|
||||
return unwrappedOther ? _value.constGet()->StrictEquals(unwrappedOther->toV8Value().constGet()) : false;
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::toBool() const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return _value.constGet()->ToBoolean(_engine->getIsolate())->Value();
|
||||
}
|
||||
|
||||
qint32 ScriptValueV8Wrapper::toInt32() const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Local<v8::Integer> *integer;
|
||||
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) {
|
||||
Q_ASSERT(false);
|
||||
|
@ -264,7 +312,10 @@ qint32 ScriptValueV8Wrapper::toInt32() const {
|
|||
}
|
||||
|
||||
double ScriptValueV8Wrapper::toInteger() const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Local<v8::Integer> *integer;
|
||||
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) {
|
||||
Q_ASSERT(false);
|
||||
|
@ -273,7 +324,10 @@ double ScriptValueV8Wrapper::toInteger() const {
|
|||
}
|
||||
|
||||
double ScriptValueV8Wrapper::toNumber() const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Local<v8::Number> *number;
|
||||
if (!_value.constGet()->ToNumber(_value.constGetContext()).ToLocal(number)) {
|
||||
Q_ASSERT(false);
|
||||
|
@ -282,14 +336,20 @@ double ScriptValueV8Wrapper::toNumber() const {
|
|||
}
|
||||
|
||||
QString ScriptValueV8Wrapper::toString() const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::String::Utf8Value string(_engine->getIsolate(), _value.constGet());
|
||||
Q_ASSERT(*string != nullptr);
|
||||
return QString(*string);
|
||||
}
|
||||
|
||||
quint16 ScriptValueV8Wrapper::toUInt16() const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Local<v8::Uint32> *integer;
|
||||
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) {
|
||||
Q_ASSERT(false);
|
||||
|
@ -298,7 +358,10 @@ quint16 ScriptValueV8Wrapper::toUInt16() const {
|
|||
}
|
||||
|
||||
quint32 ScriptValueV8Wrapper::toUInt32() const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Local<v8::Uint32> *integer;
|
||||
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) {
|
||||
Q_ASSERT(false);
|
||||
|
@ -327,7 +390,10 @@ QObject* ScriptValueV8Wrapper::toQObject() const {
|
|||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
ScriptValueV8Wrapper* unwrappedOther = unwrap(other);
|
||||
//V8TODO: does this work with different contexts/isolates?
|
||||
// in such case conversion will probably be necessary
|
||||
|
@ -343,51 +409,95 @@ bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const {
|
|||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isArray() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return _value.constGet()->IsArray();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isBool() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return _value.constGet()->IsBoolean();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isError() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
//V8TODO
|
||||
return false;
|
||||
//return _value.constGet()->IsError();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isFunction() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return _value.constGet()->IsFunction();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isNumber() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return _value.constGet()->IsNumber();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isNull() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return _value.constGet()->IsNull();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isObject() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return _value.constGet()->IsObject();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isString() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return _value.constGet()->IsString();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isUndefined() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return _value.constGet()->IsUndefined();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isValid() const {
|
||||
//V8TODO
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return true;
|
||||
//return _value.constGet()->IsValid();
|
||||
}
|
||||
|
||||
bool ScriptValueV8Wrapper::isVariant() const {
|
||||
//V8TODO
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
return false;
|
||||
//return _value.isVariant();
|
||||
}
|
||||
|
|
|
@ -27,18 +27,21 @@ public:
|
|||
V8ScriptValueTemplate(v8::Isolate *isolate, const v8::Local<T> value) : _isolate(isolate) {
|
||||
//_value.reset(_isolate, value);
|
||||
v8::HandleScope handleScope(_isolate);
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
Q_ASSERT(!isolate->GetCurrentContext().IsEmpty());
|
||||
_context.Reset(isolate, isolate->GetCurrentContext());
|
||||
_value.reset(new v8::UniquePersistent<T>(_isolate, std::move(value)));
|
||||
};
|
||||
v8::Local<T> get() {
|
||||
v8::EscapableHandleScope handleScope(_isolate);
|
||||
return _value.get()->Get(_isolate);
|
||||
return handleScope.Escape(_value.get()->Get(_isolate));
|
||||
};
|
||||
const v8::Local<T> constGet() const {
|
||||
v8::EscapableHandleScope handleScope(_isolate);
|
||||
return _value.get()->Get(_isolate);
|
||||
return handleScope.Escape(_value.get()->Get(_isolate));
|
||||
};
|
||||
V8ScriptValueTemplate<T>&& copy() const {
|
||||
Q_ASSERT(_isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(_isolate);
|
||||
return new V8ScriptValueTemplate(_isolate, v8::Local<T>::New(_isolate, constGet()));};
|
||||
const v8::Local<v8::Context> constGetContext() const {
|
||||
|
@ -72,6 +75,8 @@ public:
|
|||
V8ScriptString() = delete;
|
||||
V8ScriptString(v8::Isolate *isolate, const v8::Local<v8::String> value) : V8ScriptValueTemplate<v8::String>(isolate, value) {};
|
||||
const QString toQString() const {
|
||||
Q_ASSERT(constGet()->IsString());
|
||||
Q_ASSERT(constGetIsolate()->IsCurrent());
|
||||
return QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(constGetIsolate()), constGet()));
|
||||
};
|
||||
bool operator==(const V8ScriptString& string) const {
|
||||
|
|
Loading…
Reference in a new issue