mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-14 11:46:56 +02:00
Script engine thread safety improvements
This commit is contained in:
parent
6bd8a8d503
commit
044cd506a6
21 changed files with 374 additions and 204 deletions
|
@ -78,7 +78,7 @@ 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 {
|
||||
virtual ScriptValue globalObject() {
|
||||
Q_ASSERT(false);
|
||||
return ScriptValue();
|
||||
}
|
||||
|
@ -148,6 +148,7 @@ public: // not for public use, but I don't like how Qt strings this along with p
|
|||
virtual ScriptValue create(int type, const void* ptr) = 0;
|
||||
virtual QVariant convert(const ScriptValue& value, int type) = 0;
|
||||
virtual void registerCustomType(int type, MarshalFunction mf, DemarshalFunction df) = 0;
|
||||
virtual QStringList getCurrentScriptURLs() const = 0;
|
||||
|
||||
protected:
|
||||
~ScriptEngine() {} // prevent explicit deletion of base class
|
||||
|
|
|
@ -1139,6 +1139,7 @@ QUrl ScriptManager::resolvePath(const QString& include) const {
|
|||
do {
|
||||
auto contextInfo = context->functionContext();
|
||||
parentURL = QUrl(contextInfo->fileName());
|
||||
qDebug(scriptengine) << "ScriptManager::resolvePath: URL get: " << parentURL << " backtrace: " << context->backtrace() << " " << _engine->getCurrentScriptURLs();
|
||||
parentContext = context->parentContext();
|
||||
context = parentContext.get();
|
||||
} while (parentURL.isRelative() && context);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "v8.h"
|
||||
#include <QtCore/QDateTime>
|
||||
|
||||
#include "V8Types.h"
|
||||
//#include "V8Types.h"
|
||||
// V8TODO
|
||||
/*
|
||||
class ScriptEngineV8;
|
||||
|
|
|
@ -57,6 +57,11 @@ int ScriptContextV8Wrapper::argumentCount() const {
|
|||
v8::Context::Scope contextScope(_engine->getContext());*/
|
||||
//Q_ASSERT(_functionCallbackInfo);A
|
||||
// V8TODO
|
||||
auto isolate = _engine->getIsolate();
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
if (_functionCallbackInfo) {
|
||||
return _functionCallbackInfo->Length();
|
||||
} else if (_propertyCallbackInfo) {
|
||||
|
@ -72,12 +77,13 @@ int ScriptContextV8Wrapper::argumentCount() const {
|
|||
ScriptValue ScriptContextV8Wrapper::argument(int index) const {
|
||||
if (_functionCallbackInfo) {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
v8::Local<v8::Value> result = (*_functionCallbackInfo)[index];
|
||||
if (index < _functionCallbackInfo->kArgsLength) {
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result)));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, result)));
|
||||
} else {
|
||||
return _engine->undefinedValue();
|
||||
}
|
||||
|
@ -90,9 +96,10 @@ ScriptValue ScriptContextV8Wrapper::argument(int index) const {
|
|||
|
||||
QStringList ScriptContextV8Wrapper::backtrace() const {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 40);
|
||||
QStringList backTrace;
|
||||
//V8TODO nicer formatting
|
||||
|
@ -122,32 +129,36 @@ ScriptEnginePointer ScriptContextV8Wrapper::engine() const {
|
|||
}
|
||||
|
||||
ScriptFunctionContextPointer ScriptContextV8Wrapper::functionContext() const {
|
||||
return std::make_shared<ScriptFunctionContextV8Wrapper>(_engine);
|
||||
auto isolate = _engine->getIsolate();
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
auto scriptFunctionContextPointer = std::make_shared<ScriptFunctionContextV8Wrapper>(_engine, _context.Get(_engine->getIsolate()));
|
||||
return scriptFunctionContextPointer;
|
||||
}
|
||||
|
||||
ScriptContextPointer ScriptContextV8Wrapper::parentContext() const {
|
||||
//V8TODO
|
||||
//Q_ASSERT(false);
|
||||
//V8ScriptContext* result = _context->parentContext();
|
||||
//return result ? std::make_shared<ScriptContextV8Wrapper>(_engine, result) : ScriptContextPointer();
|
||||
return _parentContext;
|
||||
}
|
||||
|
||||
ScriptValue ScriptContextV8Wrapper::thisObject() const {
|
||||
if (_functionCallbackInfo) {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
v8::Local<v8::Value> result = _functionCallbackInfo->This();
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result)));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, result)));
|
||||
} else if (_propertyCallbackInfo) {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
v8::Local<v8::Value> result = _propertyCallbackInfo->This();
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result)));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, result)));
|
||||
} else {
|
||||
return _engine->undefinedValue();
|
||||
}
|
||||
|
@ -157,9 +168,11 @@ ScriptValue ScriptContextV8Wrapper::throwError(const QString& text) {
|
|||
auto isolate = _engine->getIsolate();
|
||||
// V8TODO: I have no idea how to do this yet because it happens on another thread
|
||||
if(isolate->IsCurrent()) {
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
V8ScriptValue result(_engine->getIsolate(),
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
V8ScriptValue result(_engine,
|
||||
_engine->getIsolate()->ThrowError(
|
||||
v8::String::NewFromUtf8(_engine->getIsolate(), text.toStdString().c_str()).ToLocalChecked()));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
|
||||
|
@ -171,21 +184,34 @@ ScriptValue ScriptContextV8Wrapper::throwError(const QString& text) {
|
|||
|
||||
ScriptValue ScriptContextV8Wrapper::throwValue(const ScriptValue& value) {
|
||||
auto isolate = _engine->getIsolate();
|
||||
Q_ASSERT(isolate->IsCurrent());
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(value);
|
||||
if (!unwrapped) {
|
||||
return _engine->undefinedValue();
|
||||
}
|
||||
V8ScriptValue result(_engine->getIsolate(), _engine->getIsolate()->ThrowException(unwrapped->toV8Value().constGet()));
|
||||
V8ScriptValue result(_engine, _engine->getIsolate()->ThrowException(unwrapped->toV8Value().constGet()));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
|
||||
}
|
||||
|
||||
ScriptFunctionContextV8Wrapper::ScriptFunctionContextV8Wrapper(ScriptEngineV8* engine, const v8::Local<v8::Context> context) : _engine(engine) {
|
||||
v8::Locker locker();
|
||||
v8::Isolate::Scope isolateScope(engine->getIsolate());
|
||||
v8::HandleScope handleScope(engine->getIsolate());
|
||||
_context.Reset(engine->getIsolate(), context);
|
||||
}
|
||||
|
||||
QString ScriptFunctionContextV8Wrapper::fileName() const {
|
||||
//V8TODO: It's not exactly like in QtScript, because there's no such context object in V8, let's return the current one for now
|
||||
//Maybe fetch data on creation or store stack frame?
|
||||
auto isolate = _engine->getIsolate();
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
// V8TODO: does this work for context selected with contextScope?
|
||||
v8::Local<v8::String> name = v8::StackTrace::CurrentScriptNameOrSourceURL(_engine->getIsolate());
|
||||
v8::String::Utf8Value nameUTF(_engine->getIsolate(), name);
|
||||
return QString(*nameUTF);
|
||||
|
@ -194,6 +220,12 @@ QString ScriptFunctionContextV8Wrapper::fileName() const {
|
|||
QString ScriptFunctionContextV8Wrapper::functionName() const {
|
||||
//V8TODO: It's not exactly like in QtScript, because there's no such context object in V8, let's return the current one for now
|
||||
//Maybe fetch data on creation?
|
||||
auto isolate = _engine->getIsolate();
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
// V8TODO: does this work for context selected with contextScope?
|
||||
v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(_engine->getIsolate(), 1);
|
||||
v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(_engine->getIsolate(), 0);
|
||||
v8::Local<v8::String> name = stackFrame->GetFunctionName();
|
||||
|
@ -210,6 +242,11 @@ ScriptFunctionContext::FunctionType ScriptFunctionContextV8Wrapper::functionType
|
|||
int ScriptFunctionContextV8Wrapper::lineNumber() const {
|
||||
//V8TODO: It's not exactly like in QtScript, because there's no such context object in V8, let's return the current one for now
|
||||
//Maybe fetch data on creation?
|
||||
auto isolate = _engine->getIsolate();
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_context.Get(isolate));
|
||||
v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(_engine->getIsolate(), 1);
|
||||
v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(_engine->getIsolate(), 0);
|
||||
return stackFrame->GetLineNumber();
|
||||
|
|
|
@ -57,6 +57,7 @@ private: // storage
|
|||
const v8::FunctionCallbackInfo<v8::Value> *_functionCallbackInfo;
|
||||
const v8::PropertyCallbackInfo<v8::Value> *_propertyCallbackInfo;
|
||||
ScriptEngineV8* _engine;
|
||||
// V8TODO: Is custom copy constructor needed for thread safety?
|
||||
v8::Persistent<v8::Context> _context;
|
||||
ScriptContextPointer _parentContext;
|
||||
};
|
||||
|
@ -64,7 +65,7 @@ private: // storage
|
|||
class ScriptFunctionContextV8Wrapper final : public ScriptFunctionContext {
|
||||
public: // construction
|
||||
//V8TODO
|
||||
inline ScriptFunctionContextV8Wrapper(ScriptEngineV8* engine) : _engine(engine) { }
|
||||
ScriptFunctionContextV8Wrapper(ScriptEngineV8* engine, const v8::Local<v8::Context> context);
|
||||
|
||||
public: // ScriptFunctionContext implementation
|
||||
virtual QString fileName() const override;
|
||||
|
@ -74,6 +75,8 @@ public: // ScriptFunctionContext implementation
|
|||
|
||||
private: // storage
|
||||
ScriptEngineV8* _engine;
|
||||
// V8TODO: Is custom copy constructor needed for thread safety?
|
||||
v8::Persistent<v8::Context> _context;
|
||||
//V8ScriptContextInfo _value;
|
||||
};
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "ScriptObjectV8Proxy.h"
|
||||
#include "ScriptProgramV8Wrapper.h"
|
||||
#include "ScriptValueV8Wrapper.h"
|
||||
#include "V8Lambda.h"
|
||||
|
||||
static const int MAX_DEBUG_VALUE_LENGTH { 80 };
|
||||
|
||||
|
@ -72,9 +73,9 @@ bool ScriptEngineV8::IS_THREADSAFE_INVOCATION(const QThread* thread, const QStri
|
|||
// engine-aware JS Error copier and factory
|
||||
V8ScriptValue ScriptEngineV8::makeError(const V8ScriptValue& _other, const QString& type) {
|
||||
if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {
|
||||
return V8ScriptValue(_v8Isolate, v8::Null(_v8Isolate));
|
||||
return V8ScriptValue(this, v8::Null(_v8Isolate));
|
||||
}
|
||||
return V8ScriptValue(_v8Isolate, v8::Null(_v8Isolate));
|
||||
return V8ScriptValue(this, v8::Null(_v8Isolate));
|
||||
//V8TODO
|
||||
/*
|
||||
auto other = _other;
|
||||
|
@ -293,7 +294,7 @@ bool ScriptEngineV8::maybeEmitUncaughtException(const QString& debugHint) {
|
|||
}
|
||||
|
||||
// Lambda
|
||||
ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8ScriptContext*, ScriptEngineV8*)> operation,
|
||||
/*ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8ScriptContext*, ScriptEngineV8*)> operation,
|
||||
const V8ScriptValue& data,
|
||||
const ValueOwnership& ownership) {
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
|
@ -305,7 +306,7 @@ ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8Scri
|
|||
call.setPrototype(object); // context->callee().prototype() === Lambda QObject
|
||||
call.setData(ScriptValue(new ScriptValueV8Wrapper(this, data))); // context->callee().data() will === data param
|
||||
return call;
|
||||
}
|
||||
}*/
|
||||
QString Lambda::toString() const {
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
|
@ -338,7 +339,7 @@ Lambda::Lambda(ScriptEngineV8* engine,
|
|||
}
|
||||
V8ScriptValue Lambda::call() {
|
||||
if (!_engine->IS_THREADSAFE_INVOCATION(__FUNCTION__)) {
|
||||
return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));
|
||||
return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
|
||||
}
|
||||
// V8TODO: it needs to be done in entirely different way for V8
|
||||
Q_ASSERT(false);
|
||||
|
@ -411,10 +412,10 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
|
|||
_contexts.append(std::make_shared<ScriptContextV8Wrapper>(this,context, ScriptContextPointer()));
|
||||
|
||||
|
||||
V8ScriptValue nullScriptValue(_v8Isolate, v8::Null(_v8Isolate));
|
||||
V8ScriptValue nullScriptValue(this, v8::Null(_v8Isolate));
|
||||
_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, nullScriptValue));
|
||||
|
||||
V8ScriptValue undefined(_v8Isolate, v8::Undefined(_v8Isolate));
|
||||
V8ScriptValue undefined(this, v8::Undefined(_v8Isolate));
|
||||
_undefinedValue = ScriptValue(new ScriptValueV8Wrapper(this, undefined));
|
||||
|
||||
registerSystemTypes();
|
||||
|
@ -463,7 +464,7 @@ void ScriptEngineV8::registerEnum(const QString& enumName, QMetaEnum newEnum) {
|
|||
for (int i = 0; i < newEnum.keyCount(); i++) {
|
||||
const char* keyName = newEnum.key(i);
|
||||
QString fullName = enumName + "." + keyName;
|
||||
registerValue(fullName, V8ScriptValue(_v8Isolate, v8::Integer::New(_v8Isolate, newEnum.keyToValue(keyName))));
|
||||
registerValue(fullName, V8ScriptValue(this, v8::Integer::New(_v8Isolate, newEnum.keyToValue(keyName))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -741,7 +742,7 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun
|
|||
v8::Local<v8::String> v8propertyName =
|
||||
v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked();
|
||||
v8::Local<v8::Object> v8ObjectToSetProperty;
|
||||
ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(V8ScriptValue(_v8Isolate, v8ParentObject));
|
||||
ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(V8ScriptValue(this, v8ParentObject));
|
||||
// If object is ScriptObjectV8Proxy, then setting property needs to be handled differently
|
||||
if (proxy) {
|
||||
v8ObjectToSetProperty = v8ParentObject->GetInternalField(2).As<v8::Object>();
|
||||
|
@ -833,13 +834,14 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
Q_ASSERT(false);
|
||||
return nullValue();
|
||||
}
|
||||
Q_ASSERT(closure.constGet()->IsObject());
|
||||
closureObject = v8::Local<v8::Object>::Cast(closure.constGet());
|
||||
qDebug() << "Closure object members:" << scriptValueDebugListMembersV8(closure);
|
||||
v8::Local<v8::Object> testObject = v8::Object::New(_v8Isolate);
|
||||
if(!testObject->Set(getContext(), v8::String::NewFromUtf8(_v8Isolate, "test_value").ToLocalChecked(), closureObject).FromMaybe(false)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
qDebug() << "Test object members:" << scriptValueDebugListMembersV8(V8ScriptValue(_v8Isolate, testObject));
|
||||
qDebug() << "Test object members:" << scriptValueDebugListMembersV8(V8ScriptValue(this, testObject));
|
||||
|
||||
if (!closureObject->Get(closure.constGetContext(), v8::String::NewFromUtf8(_v8Isolate, "global").ToLocalChecked())
|
||||
.ToLocal(&closureGlobal)) {
|
||||
|
@ -958,7 +960,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
#endif
|
||||
result = err;
|
||||
} else {
|
||||
result = ScriptValue(new ScriptValueV8Wrapper(this, V8ScriptValue(_v8Isolate, v8Result)));
|
||||
result = ScriptValue(new ScriptValueV8Wrapper(this, V8ScriptValue(this, v8Result)));
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_JS
|
||||
|
@ -1022,10 +1024,13 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
|
|||
errorLineNumber = exceptionMessage->GetLineNumber(getContext()).FromJust();
|
||||
errorColumnNumber = exceptionMessage->GetStartColumn(getContext()).FromJust();
|
||||
v8::Local<v8::Value> backtraceV8String;
|
||||
if (tryCatch.StackTrace(getContext()).ToLocal(&backtraceV8String) && backtraceV8String->IsString() &&
|
||||
v8::Local<v8::String>::Cast(backtraceV8String)->Length() > 0) {
|
||||
v8::String::Utf8Value backtraceUtf8Value(getIsolate(), backtraceV8String);
|
||||
errorBacktrace = *backtraceUtf8Value;
|
||||
if (tryCatch.StackTrace(getContext()).ToLocal(&backtraceV8String)) {
|
||||
if (backtraceV8String->IsString()) {
|
||||
if (v8::Local<v8::String>::Cast(backtraceV8String)->Length() > 0) {
|
||||
v8::String::Utf8Value backtraceUtf8Value(getIsolate(), backtraceV8String);
|
||||
errorBacktrace = *backtraceUtf8Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
qCDebug(scriptengine) << "Compiling script \"" << fileName << "\" failed on line " << errorLineNumber << " column " << errorColumnNumber << " with message: \"" << errorMessage <<"\" backtrace: " << errorBacktrace;
|
||||
}
|
||||
|
@ -1061,7 +1066,7 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
|
|||
if (!script->Run(getContext()).ToLocal(&result)) {
|
||||
Q_ASSERT(tryCatchRun.HasCaught());
|
||||
auto runError = tryCatchRun.Message();
|
||||
ScriptValue errorValue(new ScriptValueV8Wrapper(this, V8ScriptValue(_v8Isolate, runError->Get())));
|
||||
ScriptValue errorValue(new ScriptValueV8Wrapper(this, V8ScriptValue(this, runError->Get())));
|
||||
qCDebug(scriptengine) << "Running script: \"" << fileName << "\" " << formatErrorMessageFromTryCatch(tryCatchRun);
|
||||
//V8TODO
|
||||
//raiseException(errorValue);
|
||||
|
@ -1069,7 +1074,7 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
|
|||
_evaluatingCounter--;
|
||||
return errorValue;
|
||||
}
|
||||
V8ScriptValue resultValue(_v8Isolate, result);
|
||||
V8ScriptValue resultValue(this, result);
|
||||
_evaluatingCounter--;
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultValue)));
|
||||
}
|
||||
|
@ -1092,10 +1097,13 @@ QString ScriptEngineV8::formatErrorMessageFromTryCatch(v8::TryCatch &tryCatch) {
|
|||
errorLineNumber = exceptionMessage->GetLineNumber(getContext()).FromJust();
|
||||
errorColumnNumber = exceptionMessage->GetStartColumn(getContext()).FromJust();
|
||||
v8::Local<v8::Value> backtraceV8String;
|
||||
if (tryCatch.StackTrace(getContext()).ToLocal(&backtraceV8String) && backtraceV8String->IsString() &&
|
||||
v8::Local<v8::String>::Cast(backtraceV8String)->Length() > 0) {
|
||||
v8::String::Utf8Value backtraceUtf8Value(getIsolate(), backtraceV8String);
|
||||
errorBacktrace = *backtraceUtf8Value;
|
||||
if (tryCatch.StackTrace(getContext()).ToLocal(&backtraceV8String)) {
|
||||
if (backtraceV8String->IsString()) {
|
||||
if (v8::Local<v8::String>::Cast(backtraceV8String)->Length() > 0) {
|
||||
v8::String::Utf8Value backtraceUtf8Value(getIsolate(), backtraceV8String);
|
||||
errorBacktrace = *backtraceUtf8Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
QTextStream resultStream(&result);
|
||||
resultStream << "failed on line " << errorLineNumber << " column " << errorColumnNumber << " with message: \"" << errorMessage <<"\" backtrace: " << errorBacktrace;
|
||||
|
@ -1185,7 +1193,7 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro
|
|||
if (!v8Program.constGet()->Run(getContext()).ToLocal(&result)) {
|
||||
Q_ASSERT(tryCatchRun.HasCaught());
|
||||
auto runError = tryCatchRun.Message();
|
||||
errorValue = ScriptValue(new ScriptValueV8Wrapper(this, V8ScriptValue(_v8Isolate, runError->Get())));
|
||||
errorValue = ScriptValue(new ScriptValueV8Wrapper(this, V8ScriptValue(this, runError->Get())));
|
||||
raiseException(errorValue);
|
||||
maybeEmitUncaughtException("evaluate");
|
||||
hasFailed = true;
|
||||
|
@ -1195,7 +1203,7 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro
|
|||
}
|
||||
}
|
||||
if(!hasFailed) {
|
||||
V8ScriptValue resultValueV8(_v8Isolate, result);
|
||||
V8ScriptValue resultValueV8(this, result);
|
||||
resultValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultValueV8)));
|
||||
}
|
||||
}
|
||||
|
@ -1225,12 +1233,12 @@ void ScriptEngineV8::updateMemoryCost(const qint64& deltaSize) {
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ScriptEngine implementation
|
||||
|
||||
ScriptValue ScriptEngineV8::globalObject() const {
|
||||
ScriptValue ScriptEngineV8::globalObject() {
|
||||
v8::Locker locker(_v8Isolate);
|
||||
v8::Isolate::Scope isolateScope(_v8Isolate);
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getConstContext());
|
||||
V8ScriptValue global(_v8Isolate, getConstContext()->Global());// = QScriptEngine::globalObject(); // can't cache the value as it may change
|
||||
V8ScriptValue global(this, getConstContext()->Global());// = QScriptEngine::globalObject(); // can't cache the value as it may change
|
||||
return ScriptValue(new ScriptValueV8Wrapper(const_cast<ScriptEngineV8*>(this), std::move(global)));
|
||||
}
|
||||
|
||||
|
@ -1243,7 +1251,7 @@ ScriptValue ScriptEngineV8::newArray(uint length) {
|
|||
v8::Isolate::Scope isolateScope(_v8Isolate);
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getContext());
|
||||
V8ScriptValue result(_v8Isolate, v8::Array::New(_v8Isolate, static_cast<int>(length)));
|
||||
V8ScriptValue result(this, v8::Array::New(_v8Isolate, static_cast<int>(length)));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1270,7 @@ ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) {
|
|||
if (!array) {
|
||||
return undefinedValue();
|
||||
}*/
|
||||
V8ScriptValue result(_v8Isolate, arrayBuffer);//QScriptEngine::newObject(array, data);
|
||||
V8ScriptValue result(this, arrayBuffer);//QScriptEngine::newObject(array, data);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -1280,7 +1288,7 @@ ScriptValue ScriptEngineV8::newObject() {
|
|||
v8::Isolate::Scope isolateScope(_v8Isolate);
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getContext());
|
||||
V8ScriptValue resultV8 = V8ScriptValue(_v8Isolate, v8::Object::New(_v8Isolate));
|
||||
V8ScriptValue resultV8 = V8ScriptValue(this, v8::Object::New(_v8Isolate));
|
||||
result = ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultV8)));
|
||||
}
|
||||
/*if (is_isolate_exit_needed) {
|
||||
|
@ -1328,7 +1336,7 @@ ScriptValue ScriptEngineV8::newValue(bool value) {
|
|||
v8::Isolate::Scope isolateScope(_v8Isolate);
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getContext());
|
||||
V8ScriptValue result(_v8Isolate, v8::Boolean::New(_v8Isolate, value));
|
||||
V8ScriptValue result(this, v8::Boolean::New(_v8Isolate, value));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -1337,7 +1345,7 @@ ScriptValue ScriptEngineV8::newValue(int value) {
|
|||
v8::Isolate::Scope isolateScope(_v8Isolate);
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getContext());
|
||||
V8ScriptValue result(_v8Isolate, v8::Integer::New(_v8Isolate, value));
|
||||
V8ScriptValue result(this, v8::Integer::New(_v8Isolate, value));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -1346,7 +1354,7 @@ ScriptValue ScriptEngineV8::newValue(uint value) {
|
|||
v8::Isolate::Scope isolateScope(_v8Isolate);
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getContext());
|
||||
V8ScriptValue result(_v8Isolate, v8::Uint32::New(_v8Isolate, value));
|
||||
V8ScriptValue result(this, v8::Uint32::New(_v8Isolate, value));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -1355,7 +1363,7 @@ ScriptValue ScriptEngineV8::newValue(double value) {
|
|||
v8::Isolate::Scope isolateScope(_v8Isolate);
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getContext());
|
||||
V8ScriptValue result(_v8Isolate, v8::Number::New(_v8Isolate, value));
|
||||
V8ScriptValue result(this, v8::Number::New(_v8Isolate, value));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -1365,7 +1373,7 @@ ScriptValue ScriptEngineV8::newValue(const QString& value) {
|
|||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getContext());
|
||||
v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value.toStdString().c_str(), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
V8ScriptValue result(_v8Isolate, valueV8);
|
||||
V8ScriptValue result(this, valueV8);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -1375,7 +1383,7 @@ ScriptValue ScriptEngineV8::newValue(const QLatin1String& value) {
|
|||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getContext());
|
||||
v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value.latin1(), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
V8ScriptValue result(_v8Isolate, valueV8);
|
||||
V8ScriptValue result(this, valueV8);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -1385,7 +1393,7 @@ ScriptValue ScriptEngineV8::newValue(const char* value) {
|
|||
v8::HandleScope handleScope(_v8Isolate);
|
||||
v8::Context::Scope contextScope(getContext());
|
||||
v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value, v8::NewStringType::kNormal).ToLocalChecked();
|
||||
V8ScriptValue result(_v8Isolate, valueV8);
|
||||
V8ScriptValue result(this, valueV8);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -1463,6 +1471,7 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int
|
|||
v8::HandleScope handleScope(info.GetIsolate());
|
||||
auto context = info.GetIsolate()->GetCurrentContext();
|
||||
v8::Context::Scope contextScope(context);
|
||||
Q_ASSERT(info.Data()->IsObject());
|
||||
auto object = v8::Local<v8::Object>::Cast(info.Data());
|
||||
Q_ASSERT(object->InternalFieldCount() == 2);
|
||||
auto function = reinterpret_cast<ScriptEngine::FunctionSignature>
|
||||
|
@ -1493,7 +1502,7 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int
|
|||
auto v8Function = v8::Function::New(getContext(), v8FunctionCallback, functionData, length).ToLocalChecked();
|
||||
//auto functionObjectTemplate = functionTemplate->InstanceTemplate();
|
||||
//auto function =
|
||||
V8ScriptValue result(_v8Isolate, v8Function); // = QScriptEngine::newFunction(innerFunc, length);
|
||||
V8ScriptValue result(this, v8Function); // = QScriptEngine::newFunction(innerFunc, length);
|
||||
//auto funAddr = QScriptEngine::newVariant(QVariant(reinterpret_cast<qulonglong>(fun)));
|
||||
// V8TODO
|
||||
//result.setProperty("_func", funAddr, V8ScriptValue::PropertyFlags(V8ScriptValue::ReadOnly + V8ScriptValue::Undeletable + V8ScriptValue::SkipInEnumeration));
|
||||
|
@ -1685,4 +1694,20 @@ QString ScriptEngineV8::scriptValueDebugDetailsV8(const V8ScriptValue &v8Value)
|
|||
v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(_v8Isolate, n);
|
||||
|
||||
}
|
||||
}*/
|
||||
}*/
|
||||
|
||||
QStringList ScriptEngineV8::getCurrentScriptURLs() const {
|
||||
auto isolate = _v8Isolate;
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
v8::Context::Scope contextScope(_v8Isolate->GetCurrentContext());
|
||||
v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 100);
|
||||
QStringList scriptURLs;
|
||||
//V8TODO nicer formatting
|
||||
for (int i = 0; i < stackTrace->GetFrameCount(); i++) {
|
||||
v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(isolate, i);
|
||||
scriptURLs.append(QString(*v8::String::Utf8Value(isolate, stackFrame->GetScriptNameOrSourceURL())));
|
||||
}
|
||||
return scriptURLs;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include "../ScriptEngine.h"
|
||||
#include "../ScriptManager.h"
|
||||
#include "V8Types.h"
|
||||
//#include "V8Types.h"
|
||||
|
||||
#include "ArrayBufferClass.h"
|
||||
|
||||
|
@ -43,6 +43,11 @@ class ScriptEngineV8;
|
|||
class ScriptManager;
|
||||
class ScriptObjectV8Proxy;
|
||||
class ScriptMethodV8Proxy;
|
||||
|
||||
template <typename T> class V8ScriptValueTemplate;
|
||||
typedef V8ScriptValueTemplate<v8::Value> V8ScriptValue;
|
||||
typedef V8ScriptValueTemplate<v8::Script> V8ScriptProgram;
|
||||
|
||||
using ScriptContextV8Pointer = std::shared_ptr<ScriptContextV8Wrapper>;
|
||||
|
||||
const double GARBAGE_COLLECTION_TIME_LIMIT_S = 1.0;
|
||||
|
@ -69,7 +74,7 @@ public: // ScriptEngine implementation
|
|||
Q_INVOKABLE virtual ScriptValue evaluate(const QString& program, const QString& fileName = QString()) override;
|
||||
Q_INVOKABLE virtual ScriptValue evaluate(const ScriptProgramPointer& program) override;
|
||||
Q_INVOKABLE virtual ScriptValue evaluateInClosure(const ScriptValue& locals, const ScriptProgramPointer& program) override;
|
||||
virtual ScriptValue globalObject() const override;
|
||||
virtual ScriptValue globalObject() override;
|
||||
virtual bool hasUncaughtException() const override;
|
||||
virtual bool isEvaluating() const override;
|
||||
//virtual ScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1) override;
|
||||
|
@ -185,6 +190,7 @@ public: // not for public use, but I don't like how Qt strings this along with p
|
|||
QString formatErrorMessageFromTryCatch(v8::TryCatch &tryCatch);
|
||||
// Useful for debugging
|
||||
//QStringList getCurrentStackTrace();
|
||||
virtual QStringList getCurrentScriptURLs() const override;
|
||||
|
||||
using ObjectWrapperMap = QMap<QObject*, QWeakPointer<ScriptObjectV8Proxy>>;
|
||||
mutable QMutex _qobjectWrapperMapProtect;
|
||||
|
@ -193,14 +199,17 @@ public: // not for public use, but I don't like how Qt strings this along with p
|
|||
// V8TODO add a V8 callback that removes pointer from the map so that it gets deleted
|
||||
QMap<QObject*, QSharedPointer<ScriptObjectV8Proxy>> _qobjectWrapperMapV8;
|
||||
|
||||
ScriptContextV8Pointer pushContext(v8::Local<v8::Context> &context);
|
||||
void popContext();
|
||||
|
||||
protected:
|
||||
// like `newFunction`, but allows mapping inline C++ lambdas with captures as callable V8ScriptValues
|
||||
// even though the context/engine parameters are redundant in most cases, the function signature matches `newFunction`
|
||||
// anyway so that newLambdaFunction can be used to rapidly prototype / test utility APIs and then if becoming
|
||||
// permanent more easily promoted into regular static newFunction scenarios.
|
||||
ScriptValue newLambdaFunction(std::function<V8ScriptValue(V8ScriptContext* context, ScriptEngineV8* engine)> operation,
|
||||
/*ScriptValue newLambdaFunction(std::function<V8ScriptValue(V8ScriptContext* context, ScriptEngineV8* engine)> operation,
|
||||
const V8ScriptValue& data,
|
||||
const ValueOwnership& ownership = AutoOwnership);
|
||||
const ValueOwnership& ownership = AutoOwnership);*/
|
||||
|
||||
void registerSystemTypes();
|
||||
|
||||
|
@ -208,8 +217,6 @@ protected:
|
|||
static QMutex _v8InitMutex;
|
||||
static std::once_flag _v8InitOnceFlag;
|
||||
static v8::Platform* getV8Platform();
|
||||
ScriptContextV8Pointer pushContext(v8::Local<v8::Context> &context);
|
||||
void popContext();
|
||||
|
||||
// V8TODO: clean up isolate when script engine is destroyed?
|
||||
v8::Isolate* _v8Isolate;
|
||||
|
@ -239,24 +246,7 @@ protected:
|
|||
int _evaluatingCounter;
|
||||
};
|
||||
|
||||
// Lambda helps create callable V8ScriptValues out of std::functions:
|
||||
// (just meant for use from within the script engine itself)
|
||||
class Lambda : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Lambda(ScriptEngineV8* engine,
|
||||
std::function<V8ScriptValue(V8ScriptContext* context, ScriptEngineV8* engine)> operation,
|
||||
V8ScriptValue data);
|
||||
~Lambda();
|
||||
public slots:
|
||||
V8ScriptValue call();
|
||||
QString toString() const;
|
||||
|
||||
private:
|
||||
ScriptEngineV8* _engine;
|
||||
std::function<V8ScriptValue(V8ScriptContext* context, ScriptEngineV8* engine)> _operation;
|
||||
V8ScriptValue _data;
|
||||
};
|
||||
#include "V8Types.h"
|
||||
|
||||
#endif // hifi_ScriptEngineV8_h
|
||||
|
||||
|
|
|
@ -573,7 +573,7 @@ bool ScriptEngineV8::convertJSArrayToVariant(v8::Local<v8::Array> array, QVarian
|
|||
}
|
||||
QVariant property;
|
||||
// Maybe QMetaType::QVariant?
|
||||
if (castValueToVariant(V8ScriptValue(_v8Isolate, v8Property), property, QMetaType::UnknownType)) {
|
||||
if (castValueToVariant(V8ScriptValue(this, v8Property), property, QMetaType::UnknownType)) {
|
||||
properties.append(property);
|
||||
} else {
|
||||
qDebug() << "ScriptEngineV8::convertJSArrayToVariant could cast property to variant: " + QString(i);
|
||||
|
@ -603,7 +603,7 @@ bool ScriptEngineV8::convertJSObjectToVariant(v8::Local<v8::Object> object, QVar
|
|||
}
|
||||
QVariant property;
|
||||
// Maybe QMetaType::QVariant?
|
||||
if (castValueToVariant(V8ScriptValue(_v8Isolate, v8Property), property, QMetaType::UnknownType)) {
|
||||
if (castValueToVariant(V8ScriptValue(this, v8Property), property, QMetaType::UnknownType)) {
|
||||
properties.insert( name, property);
|
||||
} else {
|
||||
qDebug() << "ScriptEngineV8::convertJSObjectToVariant could cast property to variant: " + name;
|
||||
|
@ -696,51 +696,51 @@ V8ScriptValue ScriptEngineV8::castVariantToValue(const QVariant& val) {
|
|||
switch (valTypeId) {
|
||||
case QMetaType::UnknownType:
|
||||
case QMetaType::Void:
|
||||
return V8ScriptValue(_v8Isolate, v8::Undefined(_v8Isolate));
|
||||
return V8ScriptValue(this, v8::Undefined(_v8Isolate));
|
||||
case QMetaType::Nullptr:
|
||||
return V8ScriptValue(_v8Isolate, v8::Null(_v8Isolate));
|
||||
return V8ScriptValue(this, v8::Null(_v8Isolate));
|
||||
case QMetaType::Bool:
|
||||
return V8ScriptValue(_v8Isolate, v8::Boolean::New(_v8Isolate, val.toBool()));
|
||||
return V8ScriptValue(this, v8::Boolean::New(_v8Isolate, val.toBool()));
|
||||
case QMetaType::Int:
|
||||
case QMetaType::Long:
|
||||
case QMetaType::Short:
|
||||
return V8ScriptValue(_v8Isolate, v8::Integer::New(_v8Isolate, val.toInt()));
|
||||
return V8ScriptValue(this, v8::Integer::New(_v8Isolate, val.toInt()));
|
||||
case QMetaType::UInt:
|
||||
case QMetaType::UShort:
|
||||
case QMetaType::ULong:
|
||||
return V8ScriptValue(_v8Isolate, v8::Uint32::New(_v8Isolate, val.toUInt()));
|
||||
return V8ScriptValue(this, v8::Uint32::New(_v8Isolate, val.toUInt()));
|
||||
case QMetaType::ULongLong:
|
||||
return V8ScriptValue(_v8Isolate, v8::Number::New(_v8Isolate, val.toULongLong()));
|
||||
return V8ScriptValue(this, v8::Number::New(_v8Isolate, val.toULongLong()));
|
||||
case QMetaType::LongLong:
|
||||
return V8ScriptValue(_v8Isolate, v8::Number::New(_v8Isolate, val.toLongLong()));
|
||||
return V8ScriptValue(this, v8::Number::New(_v8Isolate, val.toLongLong()));
|
||||
case QMetaType::Float:
|
||||
case QMetaType::Double:
|
||||
return V8ScriptValue(_v8Isolate, v8::Number::New(_v8Isolate, val.toDouble()));
|
||||
return V8ScriptValue(this, v8::Number::New(_v8Isolate, val.toDouble()));
|
||||
case QMetaType::QString:
|
||||
case QMetaType::QByteArray:
|
||||
return V8ScriptValue(_v8Isolate, v8::String::NewFromUtf8(_v8Isolate, val.toString().toStdString().c_str()).ToLocalChecked());
|
||||
return V8ScriptValue(this, v8::String::NewFromUtf8(_v8Isolate, val.toString().toStdString().c_str()).ToLocalChecked());
|
||||
case QMetaType::QVariant:
|
||||
return castVariantToValue(val.value<QVariant>());
|
||||
case QMetaType::QObjectStar: {
|
||||
QObject* obj = val.value<QObject*>();
|
||||
if (obj == nullptr) return V8ScriptValue(_v8Isolate, v8::Null(_v8Isolate));
|
||||
if (obj == nullptr) return V8ScriptValue(this, v8::Null(_v8Isolate));
|
||||
return ScriptObjectV8Proxy::newQObject(this, obj);
|
||||
}
|
||||
case QMetaType::QDateTime:
|
||||
{
|
||||
double timeMs = val.value<QDateTime>().currentMSecsSinceEpoch();
|
||||
return V8ScriptValue(_v8Isolate, v8::Date::New(getContext(), timeMs).ToLocalChecked());
|
||||
return V8ScriptValue(this, v8::Date::New(getContext(), timeMs).ToLocalChecked());
|
||||
}
|
||||
case QMetaType::QDate:
|
||||
{
|
||||
double timeMs = val.value<QDate>().startOfDay().currentMSecsSinceEpoch();
|
||||
return V8ScriptValue(_v8Isolate, v8::Date::New(getContext(), timeMs).ToLocalChecked());
|
||||
return V8ScriptValue(this, v8::Date::New(getContext(), timeMs).ToLocalChecked());
|
||||
}
|
||||
default:
|
||||
// check to see if this is a pointer to a QObject-derived object
|
||||
if (QMetaType::typeFlags(valTypeId) & (QMetaType::PointerToQObject | QMetaType::TrackingPointerToQObject)) {
|
||||
QObject* obj = val.value<QObject*>();
|
||||
if (obj == nullptr) return V8ScriptValue(_v8Isolate, v8::Null(_v8Isolate));
|
||||
if (obj == nullptr) return V8ScriptValue(this, v8::Null(_v8Isolate));
|
||||
return ScriptObjectV8Proxy::newQObject(this, obj);
|
||||
}
|
||||
// have we set a prototype'd variant?
|
||||
|
@ -755,7 +755,7 @@ V8ScriptValue ScriptEngineV8::castVariantToValue(const QVariant& val) {
|
|||
// just do a generic variant
|
||||
//V8TODO
|
||||
Q_ASSERT(false);
|
||||
return V8ScriptValue(_v8Isolate, v8::Undefined(_v8Isolate));
|
||||
return V8ScriptValue(this, v8::Undefined(_v8Isolate));
|
||||
//return QScriptEngine::newVariant(val);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o
|
|||
QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock();
|
||||
// V8TODO: is conversion to QVariant and back needed?
|
||||
if (proxy) {
|
||||
return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value());
|
||||
return V8ScriptValue(engine, proxy.get()->toV8Value());
|
||||
}
|
||||
//if (proxy) return engine->newObject(proxy.get(), engine->newVariant(QVariant::fromValue(proxy)));;
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o
|
|||
QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock();
|
||||
//if (proxy) return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));;
|
||||
if (proxy) {
|
||||
return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value());
|
||||
return V8ScriptValue(engine, proxy.get()->toV8Value());
|
||||
}
|
||||
}
|
||||
// V8TODO add a V8 callback that removes pointer for the script engine owned ob from the map so that it gets deleted
|
||||
|
@ -133,7 +133,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o
|
|||
});
|
||||
}
|
||||
|
||||
return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value());
|
||||
return V8ScriptValue(engine, proxy.get()->toV8Value());
|
||||
//return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));
|
||||
}
|
||||
|
||||
|
@ -157,6 +157,25 @@ ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val)
|
|||
return reinterpret_cast<ScriptObjectV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));
|
||||
}
|
||||
|
||||
ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(v8::Isolate* isolate, v8::Local<v8::Value> &value) {
|
||||
//V8TODO This shouldn't cause problems but I'm not sure if it's ok
|
||||
v8::HandleScope handleScope(isolate);
|
||||
if (!value->IsObject()) {
|
||||
//qDebug(scriptengine) << "Cannot unwrap proxy - value is not an object";
|
||||
return nullptr;
|
||||
}
|
||||
v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(value);
|
||||
if (v8Object->InternalFieldCount() != 3) {
|
||||
//qDebug(scriptengine) << "Cannot unwrap proxy - wrong number of internal fields";
|
||||
return nullptr;
|
||||
}
|
||||
if (v8Object->GetAlignedPointerFromInternalField(0) != internalPointsToQObjectProxy) {
|
||||
qDebug(scriptengine) << "Cannot unwrap proxy - internal fields don't point to object proxy";
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<ScriptObjectV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));
|
||||
}
|
||||
|
||||
QObject* ScriptObjectV8Proxy::unwrap(const V8ScriptValue& val) {
|
||||
ScriptObjectV8Proxy* proxy = unwrapProxy(val);
|
||||
return proxy ? proxy->toQObject() : nullptr;
|
||||
|
@ -209,7 +228,7 @@ void ScriptObjectV8Proxy::investigate() {
|
|||
}
|
||||
|
||||
auto v8Name = v8::String::NewFromUtf8(_engine->getIsolate(), prop.name()).ToLocalChecked();
|
||||
PropertyDef& propDef = _props.insert(idx, PropertyDef(_engine->getIsolate(), v8Name)).value();
|
||||
PropertyDef& propDef = _props.insert(idx, PropertyDef(_engine, v8Name)).value();
|
||||
propDef.flags = ScriptValue::Undeletable | ScriptValue::PropertyGetter | ScriptValue::PropertySetter |
|
||||
ScriptValue::QObjectMember;
|
||||
if (prop.isConstant()) propDef.flags |= ScriptValue::ReadOnly;
|
||||
|
@ -248,11 +267,11 @@ void ScriptObjectV8Proxy::investigate() {
|
|||
}
|
||||
|
||||
auto nameString = v8::String::NewFromUtf8(_engine->getIsolate(), szName.data(), v8::NewStringType::kNormal, szName.length()).ToLocalChecked();
|
||||
V8ScriptString name(_engine->getIsolate(), nameString);
|
||||
V8ScriptString name(_engine, nameString);
|
||||
auto nameLookup = methodNames.find(name);
|
||||
if (isSignal) {
|
||||
if (nameLookup == methodNames.end()) {
|
||||
SignalDef& signalDef = _signals.insert(idx, SignalDef(_engine->getIsolate(), name.get())).value();
|
||||
SignalDef& signalDef = _signals.insert(idx, SignalDef(_engine, name.get())).value();
|
||||
signalDef.name = name;
|
||||
signalDef.signal = method;
|
||||
//qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), nameString));
|
||||
|
@ -280,7 +299,7 @@ void ScriptObjectV8Proxy::investigate() {
|
|||
}
|
||||
}
|
||||
if (nameLookup == methodNames.end()) {
|
||||
MethodDef& methodDef = _methods.insert(idx, MethodDef(_engine->getIsolate(), name.get())).value();
|
||||
MethodDef& methodDef = _methods.insert(idx, MethodDef(_engine, name.get())).value();
|
||||
methodDef.name = name;
|
||||
methodDef.numMaxParms = parameterCount;
|
||||
methodDef.methods.append(method);
|
||||
|
@ -308,7 +327,8 @@ void ScriptObjectV8Proxy::investigate() {
|
|||
// Add all the methods objects as properties - this allows adding properties to a given method later. Is used by Script.request.
|
||||
// V8TODO: Should these be deleted when the script-owned object is destroyed? It needs checking if script-owned objects will be garbage-collected, or will self-referencing prevent it.
|
||||
for (auto i = _methods.begin(); i != _methods.end(); i++) {
|
||||
V8ScriptValue method = ScriptMethodV8Proxy::newMethod(_engine, qobject, V8ScriptValue(_engine->getIsolate(), v8Object), i.value().methods, i.value().numMaxParms);
|
||||
V8ScriptValue method = ScriptMethodV8Proxy::newMethod(_engine, qobject, V8ScriptValue(_engine, v8Object),
|
||||
i.value().methods, i.value().numMaxParms);
|
||||
if(!propertiesObject->Set(_engine->getContext(), i.value().name.constGet(), method.get()).FromMaybe(false)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
@ -389,13 +409,15 @@ void ScriptObjectV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCall
|
|||
v8::HandleScope handleScope(info.GetIsolate());
|
||||
v8::String::Utf8Value utf8Value(info.GetIsolate(), name);
|
||||
//qDebug(scriptengine) << "Get: " << *utf8Value;
|
||||
V8ScriptValue object(info.GetIsolate(), info.This());
|
||||
ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(object);
|
||||
v8::Local<v8::Value> objectV8 = info.This();
|
||||
ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8);
|
||||
if (!proxy) {
|
||||
qDebug(scriptengine) << "Proxy object not found when getting: " << *utf8Value;
|
||||
return;
|
||||
}
|
||||
V8ScriptString nameString(info.GetIsolate(), v8::Local<v8::String>::Cast(name));
|
||||
V8ScriptValue object(proxy->_engine, objectV8);
|
||||
Q_ASSERT(name->IsString());
|
||||
V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name));
|
||||
uint id;
|
||||
QueryFlags flags = proxy->queryProperty(object, nameString, HandlesReadAccess, &id);
|
||||
if (flags) {
|
||||
|
@ -415,18 +437,20 @@ void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> v
|
|||
v8::HandleScope handleScope(info.GetIsolate());
|
||||
v8::String::Utf8Value utf8Value(info.GetIsolate(), name);
|
||||
//qDebug(scriptengine) << "Set: " << *utf8Value;
|
||||
V8ScriptValue object(info.GetIsolate(), info.This());
|
||||
ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(object);
|
||||
v8::Local<v8::Value> objectV8 = info.This();
|
||||
ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8);
|
||||
if (!proxy) {
|
||||
qDebug(scriptengine) << "Proxy object not found when setting: " << *utf8Value;
|
||||
return;
|
||||
}
|
||||
V8ScriptString nameString(info.GetIsolate(), v8::Local<v8::String>::Cast(name));
|
||||
V8ScriptValue object(proxy->_engine, objectV8);
|
||||
Q_ASSERT(name->IsString());
|
||||
V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name));
|
||||
//V8ScriptString nameString(info.GetIsolate(), name->ToString(proxy->_engine->getContext()).ToLocalChecked());
|
||||
uint id;
|
||||
QueryFlags flags = proxy->queryProperty(object, nameString, HandlesWriteAccess, &id);
|
||||
if (flags) {
|
||||
proxy->setProperty(object, nameString, id, V8ScriptValue(info.GetIsolate(), value));
|
||||
proxy->setProperty(object, nameString, id, V8ScriptValue(proxy->_engine, value));
|
||||
info.GetReturnValue().Set(value);
|
||||
} else {
|
||||
// V8TODO: Should it be v8::Object or v8::Local<v8::Object>?
|
||||
|
@ -447,7 +471,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
|
|||
QObject* qobject = _object;
|
||||
if (!qobject) {
|
||||
_engine->getIsolate()->ThrowError("Referencing deleted native object");
|
||||
return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));
|
||||
return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
|
||||
}
|
||||
|
||||
const QMetaObject* metaObject = qobject->metaObject();
|
||||
|
@ -456,7 +480,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
|
|||
case PROPERTY_TYPE: {
|
||||
int propId = id & ~TYPE_MASK;
|
||||
PropertyDefMap::const_iterator lookup = _props.find(propId);
|
||||
if (lookup == _props.cend()) return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));
|
||||
if (lookup == _props.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
|
||||
|
||||
QMetaProperty prop = metaObject->property(propId);
|
||||
ScriptValue scriptThis = ScriptValue(new ScriptValueV8Wrapper(_engine, object));
|
||||
|
@ -469,7 +493,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
|
|||
case METHOD_TYPE: {
|
||||
int methodId = id & ~TYPE_MASK;
|
||||
MethodDefMap::const_iterator lookup = _methods.find(methodId);
|
||||
if (lookup == _methods.cend()) return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));
|
||||
if (lookup == _methods.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
|
||||
const MethodDef& methodDef = lookup.value();
|
||||
for (auto iter = methodDef.methods.begin(); iter != methodDef.methods.end(); iter++ ) {
|
||||
if((*iter).returnType() == QMetaType::UnknownType) {
|
||||
|
@ -480,7 +504,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
|
|||
v8::Local<v8::Value> property;
|
||||
if(_v8Object.Get(_engine->getIsolate())->GetInternalField(2).As<v8::Object>()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) {
|
||||
if (!property->IsUndefined()) {
|
||||
return V8ScriptValue(_engine->getIsolate(), property);
|
||||
return V8ScriptValue(_engine, property);
|
||||
}
|
||||
}
|
||||
Q_ASSERT(false);
|
||||
|
@ -490,7 +514,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
|
|||
case SIGNAL_TYPE: {
|
||||
int signalId = id & ~TYPE_MASK;
|
||||
SignalDefMap::const_iterator defLookup = _signals.find(signalId);
|
||||
if (defLookup == _signals.cend()) return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));
|
||||
if (defLookup == _signals.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
|
||||
|
||||
InstanceMap::const_iterator instLookup = _signalInstances.find(signalId);
|
||||
if (instLookup == _signalInstances.cend() || instLookup.value().isNull()) {
|
||||
|
@ -508,7 +532,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
|
|||
//return _engine->newQObject(proxy, ScriptEngine::ScriptOwnership, options);
|
||||
}
|
||||
}
|
||||
return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));
|
||||
return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
|
||||
}
|
||||
|
||||
void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptString& name, uint id, const V8ScriptValue& value) {
|
||||
|
@ -562,7 +586,7 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa
|
|||
if (!protoProxy) {
|
||||
Q_ASSERT(protoProxy);
|
||||
//return engine->newVariant(variant);
|
||||
return V8ScriptValue(engine->getIsolate(), v8::Undefined(engine->getIsolate()));
|
||||
return V8ScriptValue(engine, v8::Undefined(engine->getIsolate()));
|
||||
}
|
||||
// V8TODO probably needs connection to be deleted
|
||||
// V8TODO what to do with proto variable?
|
||||
|
@ -572,7 +596,7 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa
|
|||
auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked();
|
||||
variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy));
|
||||
variantData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy));
|
||||
return V8ScriptValue(engine->getIsolate(), variantData);
|
||||
return V8ScriptValue(engine, variantData);
|
||||
}
|
||||
|
||||
ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) {
|
||||
|
@ -620,7 +644,7 @@ V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* ob
|
|||
// V8TODO it needs to be deleted somehow on object destruction
|
||||
methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams)));
|
||||
auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked();
|
||||
return V8ScriptValue(engine->getIsolate(), v8Function);
|
||||
return V8ScriptValue(engine, v8Function);
|
||||
}
|
||||
|
||||
QString ScriptMethodV8Proxy::fullName() const {
|
||||
|
@ -722,11 +746,11 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume
|
|||
Q_ASSERT(methodArgTypeId != QMetaType::UnknownType);
|
||||
v8::Local<v8::Value> argVal = arguments[arg];
|
||||
if (methodArgTypeId == scriptValueTypeId) {
|
||||
qScriptArgLists[i].append(ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(isolate, argVal))));
|
||||
qScriptArgLists[i].append(ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, argVal))));
|
||||
qGenArgsVectors[i][arg] = Q_ARG(ScriptValue, qScriptArgLists[i].back());
|
||||
} else if (methodArgTypeId == QMetaType::QVariant) {
|
||||
QVariant varArgVal;
|
||||
if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) {
|
||||
if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) {
|
||||
conversionFailures++;
|
||||
} else {
|
||||
qVarArgLists[i].append(varArgVal);
|
||||
|
@ -734,12 +758,12 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume
|
|||
}
|
||||
} else {
|
||||
QVariant varArgVal;
|
||||
if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) {
|
||||
if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) {
|
||||
conversionFailures++;
|
||||
} else {
|
||||
qVarArgLists[i].append(varArgVal);
|
||||
const QVariant& converted = qVarArgLists[i].back();
|
||||
conversionPenaltyScore = _engine->computeCastPenalty(V8ScriptValue(isolate, argVal), methodArgTypeId);
|
||||
conversionPenaltyScore = _engine->computeCastPenalty(V8ScriptValue(_engine, argVal), methodArgTypeId);
|
||||
|
||||
// a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant
|
||||
// A const_cast is needed because calling data() would detach the QVariant.
|
||||
|
@ -834,9 +858,9 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume
|
|||
v8::Local<v8::Value> argVal = arguments[arg];
|
||||
if (methodArgTypeId != scriptValueTypeId) {
|
||||
QVariant varArgVal;
|
||||
if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) {
|
||||
if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) {
|
||||
QByteArray methodTypeName = QMetaType(methodArgTypeId).name();
|
||||
QByteArray argTypeName = _engine->valueType(V8ScriptValue(isolate, argVal)).toLatin1();
|
||||
QByteArray argTypeName = _engine->valueType(V8ScriptValue(_engine, 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 << "\n Backtrace:" << _engine->currentContext()->backtrace();
|
||||
|
@ -1043,6 +1067,8 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu
|
|||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
v8::HandleScope handleScope(isolate);
|
||||
// V8TODO: should we use function creation context, or context in which connect happened?
|
||||
|
||||
auto context = _engine->getContext();
|
||||
v8::Context::Scope contextScope(context);
|
||||
|
||||
|
@ -1063,20 +1089,29 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu
|
|||
|
||||
for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) {
|
||||
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()->IsObject()) {
|
||||
v8This = conn.thisValue.get();
|
||||
} else {
|
||||
v8This = _engine->getContext()->Global();
|
||||
}
|
||||
Q_ASSERT(!conn.callback.get().IsEmpty());
|
||||
Q_ASSERT(!conn.callback.get()->IsUndefined());
|
||||
Q_ASSERT(conn.callback.get()->IsFunction());
|
||||
{
|
||||
v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(conn.callback.get());
|
||||
auto functionContext = callback->CreationContext();
|
||||
_engine->pushContext(functionContext);
|
||||
v8::Context::Scope functionContextScope(functionContext);
|
||||
v8::Local<v8::Value> v8This;
|
||||
if (conn.thisValue.get()->IsObject()) {
|
||||
v8This = conn.thisValue.get();
|
||||
} else {
|
||||
v8This = _engine->getContext()->Global();
|
||||
}
|
||||
|
||||
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)
|
||||
<< "\nThis provided: " << conn.thisValue.get()->IsObject();
|
||||
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)
|
||||
<< "\nThis provided: " << conn.thisValue.get()->IsObject();
|
||||
}
|
||||
_engine->popContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1125,8 +1160,8 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) {
|
|||
//v8::HandleScope handleScope(isolate);
|
||||
|
||||
// untangle the arguments
|
||||
V8ScriptValue callback(isolate, v8::Null(isolate));
|
||||
V8ScriptValue callbackThis(isolate, v8::Null(isolate));
|
||||
V8ScriptValue callback(_engine, v8::Null(isolate));
|
||||
V8ScriptValue callbackThis(_engine, v8::Null(isolate));
|
||||
if (arg1.isFunction()) {
|
||||
auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
|
||||
auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);
|
||||
|
@ -1158,6 +1193,9 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) {
|
|||
}
|
||||
|
||||
// add a reference to ourselves to the destination callback
|
||||
Q_ASSERT(!callback.get().IsEmpty());
|
||||
Q_ASSERT(!callback.get()->IsUndefined());
|
||||
Q_ASSERT(callback.get()->IsFunction());
|
||||
v8::Local<v8::Function> destFunction = v8::Local<v8::Function>::Cast(callback.get());
|
||||
v8::Local<v8::String> destDataName = v8::String::NewFromUtf8(isolate, "__data__").ToLocalChecked();
|
||||
v8::Local<v8::Value> destData;
|
||||
|
@ -1166,7 +1204,10 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) {
|
|||
//Q_ASSERT(destFunction->InternalFieldCount() == 4);
|
||||
//Q_ASSERT(destData.get()->IsArray());
|
||||
//v8::Local<v8::Value> destData = destFunction->GetInternalField(3);
|
||||
if (destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData) && destData->IsArray()) {
|
||||
if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
if (destData->IsArray()) {
|
||||
v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData);
|
||||
int length = destArray->Length();//destData.property("length").toInteger();
|
||||
v8::Local<v8::Array> newArray = v8::Array::New(isolate, length + 1);
|
||||
|
@ -1232,8 +1273,8 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) {
|
|||
v8::Context::Scope contextScope(_engine->getContext());
|
||||
|
||||
// untangle the arguments
|
||||
V8ScriptValue callback(isolate, v8::Null(isolate));
|
||||
V8ScriptValue callbackThis(isolate, v8::Null(isolate));
|
||||
V8ScriptValue callback(_engine, v8::Null(isolate));
|
||||
V8ScriptValue callbackThis(_engine, v8::Null(isolate));
|
||||
if (arg1.isFunction()) {
|
||||
auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
|
||||
auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);
|
||||
|
@ -1277,7 +1318,10 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) {
|
|||
V8ScriptValue v8ThisObject = ScriptValueV8Wrapper::fullUnwrap(_engine, thisObject());
|
||||
//V8ScriptValue destData = callback.data();
|
||||
//Q_ASSERT(destData->IsArray());
|
||||
if (destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData) && destData->IsArray()) {
|
||||
if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
if (destData->IsArray()) {
|
||||
v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData);
|
||||
int length = destArray->Length();//destData.property("length").toInteger();
|
||||
v8::Local<v8::Array> newArray = v8::Array::New(isolate, length - 1);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "../ScriptEngine.h"
|
||||
#include "../Scriptable.h"
|
||||
#include "ScriptEngineV8.h"
|
||||
#include "V8Types.h"
|
||||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
|
@ -37,20 +38,20 @@ class ScriptObjectV8Proxy final {
|
|||
private: // implementation
|
||||
class PropertyDef {
|
||||
public:
|
||||
PropertyDef(v8::Isolate *isolate, v8::Local<v8::String> string) : name(isolate, string) {};
|
||||
PropertyDef(ScriptEngineV8 *engine, v8::Local<v8::String> string) : name(engine, string) {};
|
||||
V8ScriptString name;
|
||||
ScriptValue::PropertyFlags flags;
|
||||
};
|
||||
class MethodDef {
|
||||
public:
|
||||
MethodDef(v8::Isolate *isolate, v8::Local<v8::String> string) : name(isolate, string) {};
|
||||
MethodDef(ScriptEngineV8 *engine, v8::Local<v8::String> string) : name(engine, string) {};
|
||||
V8ScriptString name;
|
||||
int numMaxParms;
|
||||
QList<QMetaMethod> methods;
|
||||
};
|
||||
class SignalDef {
|
||||
public:
|
||||
SignalDef(v8::Isolate *isolate, v8::Local<v8::String> string) : name(isolate, string) {};
|
||||
SignalDef(ScriptEngineV8 *engine, v8::Local<v8::String> string) : name(engine, string) {};
|
||||
V8ScriptString name;
|
||||
QMetaMethod signal;
|
||||
};
|
||||
|
@ -73,6 +74,7 @@ public: // construction
|
|||
ScriptEngine::ValueOwnership ownership = ScriptEngine::QtOwnership,
|
||||
const ScriptEngine::QObjectWrapOptions& options = ScriptEngine::QObjectWrapOptions());
|
||||
static ScriptObjectV8Proxy* unwrapProxy(const V8ScriptValue& val);
|
||||
static ScriptObjectV8Proxy* unwrapProxy(v8::Isolate* isolate, v8::Local<v8::Value>& value);
|
||||
static QObject* unwrap(const V8ScriptValue& val);
|
||||
inline QObject* toQObject() const { return _object; }
|
||||
inline v8::Local<v8::Object> toV8Value() const {
|
||||
|
|
|
@ -52,9 +52,9 @@ bool ScriptProgramV8Wrapper::compile() {
|
|||
v8::ScriptOrigin scriptOrigin(isolate, v8::String::NewFromUtf8(isolate, _url.toStdString().c_str()).ToLocalChecked());
|
||||
v8::Local<v8::Script> script;
|
||||
if (v8::Script::Compile(context, v8::String::NewFromUtf8(isolate, _source.toStdString().c_str()).ToLocalChecked(), &scriptOrigin).ToLocal(&script)) {
|
||||
qDebug() << "Script compilation succesful: " << _url;
|
||||
qDebug() << "Script compilation successful: " << _url;
|
||||
_compileResult = ScriptSyntaxCheckResultV8Wrapper(ScriptSyntaxCheckResult::Valid);
|
||||
_value = V8ScriptProgram(isolate, script);
|
||||
_value = V8ScriptProgram(_engine, script);
|
||||
_isCompiled = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -66,10 +66,13 @@ bool ScriptProgramV8Wrapper::compile() {
|
|||
errorLineNumber = exceptionMessage->GetLineNumber(context).FromJust();
|
||||
errorColumnNumber = exceptionMessage->GetStartColumn(context).FromJust();
|
||||
v8::Local<v8::Value> backtraceV8String;
|
||||
if (tryCatch.StackTrace(context).ToLocal(&backtraceV8String) && backtraceV8String->IsString() &&
|
||||
v8::Local<v8::String>::Cast(backtraceV8String)->Length() > 0) {
|
||||
v8::String::Utf8Value backtraceUtf8Value(isolate, backtraceV8String);
|
||||
errorBacktrace = *backtraceUtf8Value;
|
||||
if (tryCatch.StackTrace(context).ToLocal(&backtraceV8String)) {
|
||||
if (backtraceV8String->IsString()) {
|
||||
if (v8::Local<v8::String>::Cast(backtraceV8String)->Length() > 0) {
|
||||
v8::String::Utf8Value backtraceUtf8Value(isolate, backtraceV8String);
|
||||
errorBacktrace = *backtraceUtf8Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//V8TODO
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "../ScriptProgram.h"
|
||||
#include "ScriptEngineV8.h"
|
||||
#include "V8Types.h"
|
||||
|
||||
class ScriptSyntaxCheckResultV8Wrapper final : public ScriptSyntaxCheckResult {
|
||||
public: // construction
|
||||
|
@ -51,7 +52,7 @@ public: // construction
|
|||
//inline ScriptProgramV8Wrapper(ScriptEngineV8* engine, V8ScriptProgram&& value) :
|
||||
// _engine(engine), _value(std::move(value)) {}
|
||||
inline ScriptProgramV8Wrapper(ScriptEngineV8* engine, QString source, QString url) :
|
||||
_engine(engine), _source(source), _url(url), _value(engine->getIsolate(), v8::Local<v8::Script>()) {}
|
||||
_engine(engine), _source(source), _url(url), _value(engine, v8::Local<v8::Script>()) {}
|
||||
static ScriptProgramV8Wrapper* unwrap(ScriptProgramPointer val);
|
||||
bool compile();
|
||||
inline const V8ScriptProgram& toV8Value() const { return _value; }
|
||||
|
|
|
@ -71,7 +71,7 @@ V8ScriptValue V8ScriptValueIterator::value() {
|
|||
if (!_object.Get(isolate)->Get(context, propertyName->ToString(context).ToLocalChecked()).ToLocal(&v8Value)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
return V8ScriptValue(isolate, v8Value);
|
||||
return V8ScriptValue(_engine, v8Value);
|
||||
}
|
||||
|
||||
ScriptValue::PropertyFlags ScriptValueIteratorV8Wrapper::flags() const {
|
||||
|
|
|
@ -82,7 +82,7 @@ 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: IsFunction check should be here probably
|
||||
Q_ASSERT(_value.get()->IsFunction());
|
||||
v8::Local<v8::Function> v8Function = v8::Local<v8::Function>::Cast(_value.get());
|
||||
v8::TryCatch tryCatch(isolate);
|
||||
v8::Local<v8::Value> recv;
|
||||
|
@ -101,7 +101,7 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
|
|||
}
|
||||
v8::Local<v8::Value> result;
|
||||
if (maybeResult.ToLocal(&result)) {
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result)));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, result)));
|
||||
} else {
|
||||
//V8TODO Add more details
|
||||
qWarning("JS function call failed");
|
||||
|
@ -135,6 +135,7 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
|
|||
}
|
||||
|
||||
ScriptValue ScriptValueV8Wrapper::construct(const ScriptValueList& args) {
|
||||
//V8TODO: there is CallAsContructor in V8
|
||||
auto isolate = _engine->getIsolate();
|
||||
v8::Locker locker(isolate);
|
||||
v8::Isolate::Scope isolateScope(isolate);
|
||||
|
@ -148,12 +149,12 @@ ScriptValue ScriptValueV8Wrapper::construct(const ScriptValueList& args) {
|
|||
v8Args[argIndex++] = fullUnwrap(*iter).get();
|
||||
}
|
||||
//V8TODO should there be a v8 try-catch here?
|
||||
// IsFunction check should be here probably
|
||||
Q_ASSERT(_value.get()->IsFunction());
|
||||
v8::Local<v8::Function> v8Function = v8::Local<v8::Function>::Cast(_value.get());
|
||||
auto maybeResult = v8Function->NewInstance(_engine->getContext(), args.length(), v8Args);
|
||||
v8::Local<v8::Object> result;
|
||||
if (maybeResult.ToLocal(&result)) {
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result)));
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, result)));
|
||||
} else {
|
||||
//V8TODO Add more details
|
||||
qWarning("JS function call failed");
|
||||
|
@ -203,7 +204,7 @@ ScriptValue ScriptValueV8Wrapper::data() const {
|
|||
Q_ASSERT(false);
|
||||
}
|
||||
}*/
|
||||
V8ScriptValue result(isolate, data);
|
||||
V8ScriptValue result(_engine, data);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
|
||||
} else {
|
||||
qDebug() << "ScriptValueV8Wrapper::data() was called on a value that is not an object";
|
||||
|
@ -268,7 +269,7 @@ ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValu
|
|||
//V8TODO: Which context?
|
||||
if (object->Get(_engine->getContext(), key).ToLocal(&resultLocal)) {
|
||||
//if (object->Get(_value.constGetContext(), key).ToLocal(&resultLocal)) {
|
||||
V8ScriptValue result(_engine->getIsolate(), resultLocal);
|
||||
V8ScriptValue result(_engine, resultLocal);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
|
||||
} else {
|
||||
QString parentValueQString("");
|
||||
|
@ -303,7 +304,7 @@ ScriptValue ScriptValueV8Wrapper::property(quint32 arrayIndex, const ScriptValue
|
|||
v8::Local<v8::Value> resultLocal;
|
||||
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);
|
||||
V8ScriptValue result(_engine, resultLocal);
|
||||
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "../ScriptValue.h"
|
||||
#include "ScriptEngineV8.h"
|
||||
#include "V8Types.h"
|
||||
|
||||
/// [V8] Implements ScriptValue for V8 and translates calls for V8ScriptValue
|
||||
class ScriptValueV8Wrapper final : public ScriptValueProxy {
|
||||
|
|
41
libraries/script-engine/src/v8/V8Lambda.h
Normal file
41
libraries/script-engine/src/v8/V8Lambda.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// V8Lambda.h
|
||||
// split from ScriptEngineV8.h
|
||||
// libraries/script-engine/src/qtscript
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/14/13.
|
||||
// Modified for V8 by dr Karol Suprynowicz on 2022/10/08
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
// Copyright 2022 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_V8Lambda_h
|
||||
#define hifi_V8Lambda_h
|
||||
|
||||
#include "ScriptEngineV8.h"
|
||||
#include "V8Types.h"
|
||||
|
||||
// Lambda helps create callable V8ScriptValues out of std::functions:
|
||||
// (just meant for use from within the script engine itself)
|
||||
class Lambda : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Lambda(ScriptEngineV8* engine,
|
||||
std::function<V8ScriptValue(V8ScriptContext* context, ScriptEngineV8* engine)> operation,
|
||||
V8ScriptValue data);
|
||||
~Lambda();
|
||||
public slots:
|
||||
V8ScriptValue call();
|
||||
QString toString() const;
|
||||
|
||||
private:
|
||||
ScriptEngineV8* _engine;
|
||||
std::function<V8ScriptValue(V8ScriptContext* context, ScriptEngineV8* engine)> _operation;
|
||||
V8ScriptValue _data;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -17,6 +17,8 @@
|
|||
#include <libplatform/libplatform.h>
|
||||
#include <v8.h>
|
||||
|
||||
#include "ScriptEngineV8.h"
|
||||
|
||||
template <typename T>
|
||||
class V8ScriptValueTemplate {
|
||||
public:
|
||||
|
@ -24,66 +26,83 @@ public:
|
|||
//V8ScriptValueTemplate(v8::Isolate *isolate, v8::Local<T> value) : _isolate(isolate) {
|
||||
//_value.reset(v8::UniquePersistent<T>::New(_isolate, value));
|
||||
//};
|
||||
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)));
|
||||
V8ScriptValueTemplate(ScriptEngineV8 *engine, const v8::Local<T> value) : _engine(engine) {
|
||||
v8::Locker locker(_engine->getIsolate());
|
||||
v8::Isolate::Scope isolateScope(_engine->getIsolate());
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
v8::Context::Scope(_engine->getContext());
|
||||
_value.reset(new v8::UniquePersistent<T>(_engine->getIsolate(), std::move(value)));
|
||||
};
|
||||
|
||||
/*V8ScriptValueTemplate(const V8ScriptValueTemplate &copied) {
|
||||
;
|
||||
}*/
|
||||
V8ScriptValueTemplate(const V8ScriptValueTemplate &copied) : _engine(copied.getEngine()) {
|
||||
v8::Locker locker(_engine->getIsolate());
|
||||
v8::Isolate::Scope isolateScope(_engine->getIsolate());
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
v8::Context::Scope(_engine->getContext());
|
||||
_value.reset(new v8::UniquePersistent<T>(_engine->getIsolate(), std::move(copied.constGet())));
|
||||
}
|
||||
|
||||
v8::Local<T> get() {
|
||||
v8::EscapableHandleScope handleScope(_isolate);
|
||||
return handleScope.Escape(_value.get()->Get(_isolate));
|
||||
Q_ASSERT(_engine->getIsolate()->IsCurrent());
|
||||
v8::EscapableHandleScope handleScope(_engine->getIsolate());
|
||||
return handleScope.Escape(_value.get()->Get(_engine->getIsolate()));
|
||||
};
|
||||
|
||||
const v8::Local<T> constGet() const {
|
||||
v8::EscapableHandleScope handleScope(_isolate);
|
||||
return handleScope.Escape(_value.get()->Get(_isolate));
|
||||
Q_ASSERT(_engine->getIsolate()->IsCurrent());
|
||||
v8::EscapableHandleScope handleScope(_engine->getIsolate());
|
||||
return handleScope.Escape(_value.get()->Get(_engine->getIsolate()));
|
||||
};
|
||||
V8ScriptValueTemplate<T>&& copy() const {
|
||||
Q_ASSERT(_isolate->IsCurrent());
|
||||
v8::HandleScope handleScope(_isolate);
|
||||
return new V8ScriptValueTemplate(_isolate, v8::Local<T>::New(_isolate, constGet()));};
|
||||
|
||||
/*V8ScriptValueTemplate<T>&& copy() const {
|
||||
Q_ASSERT(_engine->getIsolate()->IsCurrent());
|
||||
v8::HandleScope handleScope(_engine->getIsolate());
|
||||
return new V8ScriptValueTemplate(_engine->getIsolate(), v8::Local<T>::New(_engine->getIsolate(), constGet()));
|
||||
};*/
|
||||
|
||||
const v8::Local<v8::Context> constGetContext() const {
|
||||
v8::EscapableHandleScope handleScope(_isolate);
|
||||
Q_ASSERT(!_isolate->GetCurrentContext().IsEmpty());
|
||||
return handleScope.Escape(_isolate->GetCurrentContext());
|
||||
Q_ASSERT(_engine->getIsolate()->IsCurrent());
|
||||
v8::EscapableHandleScope handleScope(_engine->getIsolate());
|
||||
return handleScope.Escape(_engine->getIsolate()->GetCurrentContext());
|
||||
//return handleScope.Escape(_context.Get(_isolate));
|
||||
};
|
||||
const v8::Isolate* constGetIsolate() const { return _isolate;};
|
||||
v8::Isolate* getIsolate() { return _isolate;};
|
||||
|
||||
const v8::Isolate* constGetIsolate() const { return _engine->getIsolate(); };
|
||||
v8::Isolate* getIsolate() { return _engine->getIsolate();};
|
||||
|
||||
//v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>>& getContext() { return _context;};
|
||||
|
||||
ScriptEngineV8* getEngine() const { return _engine; };
|
||||
|
||||
v8::Local<v8::Context> getContext() {
|
||||
v8::EscapableHandleScope handleScope(_isolate);
|
||||
Q_ASSERT(!_isolate->GetCurrentContext().IsEmpty());
|
||||
return handleScope.Escape(_isolate->GetCurrentContext());
|
||||
Q_ASSERT(_engine->getIsolate()->IsCurrent());
|
||||
v8::EscapableHandleScope handleScope(_engine->getIsolate());
|
||||
return handleScope.Escape(_engine->getIsolate()->GetCurrentContext());
|
||||
//return handleScope.Escape(_context.Get(_isolate));
|
||||
};
|
||||
void reset(v8::Isolate *isolate, v8::Local<T>) {};
|
||||
|
||||
void reset(v8::Isolate *isolate, v8::Local<T>) {
|
||||
Q_ASSERT(false);
|
||||
};
|
||||
private:
|
||||
std::shared_ptr<v8::UniquePersistent<T>> _value;
|
||||
// V8TODO: maybe make it weak
|
||||
// does it need , CopyablePersistentTraits<Value>?
|
||||
// V8TODO: is context needed at all?
|
||||
v8::Isolate *_isolate;
|
||||
v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>> _context;
|
||||
//v8::Isolate *_isolate;
|
||||
ScriptEngineV8 *_engine;
|
||||
//v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>> _context;
|
||||
};
|
||||
|
||||
typedef V8ScriptValueTemplate<v8::Value> V8ScriptValue;
|
||||
typedef V8ScriptValueTemplate<v8::Script> V8ScriptProgram;
|
||||
//typedef V8ScriptValueTemplate<v8::Value> V8ScriptValue;
|
||||
//typedef V8ScriptValueTemplate<v8::Script> V8ScriptProgram;
|
||||
// V8TODO: Maybe weak?
|
||||
typedef v8::Persistent<v8::Context> V8ScriptContext;
|
||||
|
||||
class V8ScriptString : public V8ScriptValueTemplate<v8::String> {
|
||||
public:
|
||||
V8ScriptString() = delete;
|
||||
V8ScriptString(v8::Isolate *isolate, const v8::Local<v8::String> value) : V8ScriptValueTemplate<v8::String>(isolate, value) {};
|
||||
V8ScriptString(ScriptEngineV8 *engine, const v8::Local<v8::String> value) : V8ScriptValueTemplate<v8::String>(engine, value) {};
|
||||
const QString toQString() const {
|
||||
Q_ASSERT(constGetIsolate()->IsCurrent());
|
||||
Q_ASSERT(constGet()->IsString());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"use strict";
|
||||
"no use strict";
|
||||
|
||||
// inEditMode.js
|
||||
//
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"use strict";
|
||||
"no use strict";
|
||||
|
||||
// inVREditMode.js
|
||||
//
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"use strict";
|
||||
"no use strict";
|
||||
|
||||
// stylusInput.js
|
||||
//
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"use strict";
|
||||
"no use strict";
|
||||
|
||||
// createWindow.js
|
||||
//
|
||||
|
@ -71,6 +71,7 @@ var CallableEvent = (function() {
|
|||
module.exports = (function() {
|
||||
function CreateWindow(qmlPath, title, settingsKey, defaultRect, createOnStartup) {
|
||||
this.qmlPath = qmlPath;
|
||||
print("QML path: " + qmlPath);
|
||||
this.title = title;
|
||||
this.settingsKey = settingsKey;
|
||||
this.defaultRect = defaultRect;
|
||||
|
|
Loading…
Reference in a new issue