Add V8 handle scopes

This commit is contained in:
ksuprynowicz 2022-10-08 16:30:36 +02:00
parent b4d21c38c3
commit 2b06c09318
10 changed files with 135 additions and 43 deletions

View file

@ -33,7 +33,8 @@ ScriptContextV8Wrapper* ScriptContextV8Wrapper::unwrap(ScriptContext* val) {
}
v8::Local<v8::Context> ScriptContextV8Wrapper::toV8Value() const {
return _context.Get(_engine->getIsolate());
v8::EscapableHandleScope handleScope(_engine->getIsolate());
return handleScope.Escape(_context.Get(_engine->getIsolate()));
}
int ScriptContextV8Wrapper::argumentCount() const {
@ -42,6 +43,7 @@ int ScriptContextV8Wrapper::argumentCount() const {
}
ScriptValue ScriptContextV8Wrapper::argument(int index) const {
v8::HandleScope handleScope(_engine->getIsolate());
Q_ASSERT(_functionCallbackInfo);
v8::Local<v8::Value> result = (*_functionCallbackInfo)[index];
//V8ScriptValue result = _context->argument(index);
@ -50,6 +52,7 @@ ScriptValue ScriptContextV8Wrapper::argument(int index) const {
QStringList ScriptContextV8Wrapper::backtrace() const {
auto isolate = _engine->getIsolate();
v8::HandleScope handleScope(isolate);
v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 40);
QStringList backTrace;
//V8TODO nicer formatting
@ -90,17 +93,20 @@ ScriptContextPointer ScriptContextV8Wrapper::parentContext() const {
ScriptValue ScriptContextV8Wrapper::thisObject() const {
Q_ASSERT(_functionCallbackInfo);
v8::HandleScope handleScope(_engine->getIsolate());
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());
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());
ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(value);
if (!unwrapped) {
return _engine->undefinedValue();

View file

@ -56,6 +56,7 @@ private: // storage
class ScriptFunctionContextV8Wrapper final : public ScriptFunctionContext {
public: // construction
//V8TODO
inline ScriptFunctionContextV8Wrapper(v8::Local<v8::Context> context) { }
public: // ScriptFunctionContext implementation

View file

@ -293,6 +293,7 @@ ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8Scri
return call;
}
QString Lambda::toString() const {
v8::HandleScope handleScope(_engine->getIsolate());
v8::Local<v8::String> string;
QString qString("");
if (_data.constGet()->ToString(_engine->getContext()).ToLocal(&string)) {
@ -372,6 +373,7 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
v8::Isolate::CreateParams isolateParams;
isolateParams.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
_v8Isolate = v8::Isolate::New(isolateParams);
v8::HandleScope handleScope(_v8Isolate);
v8::Local<v8::Context> context = v8::Context::New(_v8Isolate);
_v8Context = v8::UniquePersistent<v8::Context>(_v8Isolate, context);
@ -434,7 +436,7 @@ void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value
Q_ARG(V8ScriptValue, value));
return;
}*/
v8::HandleScope handleScope(_v8Isolate);
QStringList pathToValue = valueName.split(".");
int partsToGo = pathToValue.length();
v8::Local<v8::Object> partObject = _v8Context.Get(_v8Isolate)->Global();
@ -449,15 +451,21 @@ void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value
//QObject *object = new QObject;
v8::Local<v8::Object> partValue = v8::Object::New(_v8Isolate); //newQObject(object, QScriptEngine::ScriptOwnership);
//V8ScriptValue partValue = QScriptEngine::newArray(); //newQObject(object, QScriptEngine::ScriptOwnership);
Q_ASSERT(partObject->Set(_v8Context.Get(_v8Isolate), pathPartV8, partValue).FromMaybe(false));
if (!partObject->Set(_v8Context.Get(_v8Isolate), pathPartV8, partValue).FromMaybe(false)) {
Q_ASSERT(false);
}
} else {
//partObject = currentPath->ToObject();
//V8TODO: do these still happen if asserts are disabled?
Q_ASSERT(partObject->Set(_v8Context.Get(_v8Isolate), pathPartV8, value.constGet()).FromMaybe(false));
if (!partObject->Set(_v8Context.Get(_v8Isolate), pathPartV8, value.constGet()).FromMaybe(false)) {
Q_ASSERT(false);
}
}
}
v8::Local<v8::Value> child;
Q_ASSERT(partObject->Get(_v8Context.Get(_v8Isolate), pathPartV8).ToLocal(&child));
if (!partObject->Get(_v8Context.Get(_v8Isolate), pathPartV8).ToLocal(&child)) {
Q_ASSERT(false);
}
}
}
@ -475,6 +483,7 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object)
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "ScriptEngineV8::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name;
#endif*/
v8::HandleScope handleScope(_v8Isolate);
v8::Local<v8::Object> v8GlobalObject = getContext()->Global();
v8::Local<v8::String> v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked();
@ -575,6 +584,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {
return nullValue();
}
v8::HandleScope handleScope(_v8Isolate);
ScriptProgramV8Wrapper* unwrappedProgram = ScriptProgramV8Wrapper::unwrap(_program);
if (unwrappedProgram == nullptr) {
return nullValue();
@ -699,6 +709,7 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
}*/
// Compile and check syntax
// V8TODO: Could these all be replaced with checkSyntax function from wrapper?
v8::HandleScope handleScope(_v8Isolate);
v8::TryCatch tryCatch(getIsolate());
v8::ScriptOrigin scriptOrigin(getIsolate(), v8::String::NewFromUtf8(getIsolate(), fileName.toStdString().c_str()).ToLocalChecked());
v8::Local<v8::Script> script;
@ -776,7 +787,7 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro
Q_ARG(const ScriptProgramPointer&, program));
return result;
}*/
v8::HandleScope handleScope(_v8Isolate);
ScriptProgramV8Wrapper* unwrapped = ScriptProgramV8Wrapper::unwrap(program);
if (!unwrapped) {
auto err = makeError(newValue("could not unwrap program"));
@ -831,6 +842,7 @@ void ScriptEngineV8::updateMemoryCost(const qint64& deltaSize) {
// ScriptEngine implementation
ScriptValue ScriptEngineV8::globalObject() const {
v8::HandleScope handleScope(_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)));
}
@ -845,6 +857,7 @@ ScriptValue ScriptEngineV8::newArray(uint length) {
}
ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) {
v8::HandleScope handleScope(_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());
@ -900,23 +913,27 @@ ScriptValue ScriptEngineV8::newValue(uint value) {
}
ScriptValue ScriptEngineV8::newValue(double value) {
v8::HandleScope handleScope(_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::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)));
}
ScriptValue ScriptEngineV8::newValue(const QLatin1String& value) {
v8::HandleScope handleScope(_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)));
}
ScriptValue ScriptEngineV8::newValue(const char* value) {
v8::HandleScope handleScope(_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)));
@ -986,6 +1003,7 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int
auto v8FunctionCallback = [](const v8::FunctionCallbackInfo<v8::Value>& info) {
//V8TODO: is using GetCurrentContext ok, or context wrapper needs to be added?
v8::HandleScope handleScope(info.GetIsolate());
auto context = info.GetIsolate()->GetCurrentContext();
auto function = reinterpret_cast<ScriptEngine::FunctionSignature>
(info.Data()->ToObject(context).ToLocalChecked()->GetAlignedPointerFromInternalField(0));
@ -1000,6 +1018,7 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int
//auto functionTemplate = v8::FunctionTemplate::New(_v8Isolate, v8FunctionCallback, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), length);
//auto functionData = v8::Object::New(_v8Isolate);
//functionData->setIn
v8::HandleScope handleScope(_v8Isolate);
auto functionDataTemplate = v8::ObjectTemplate::New(_v8Isolate);
functionDataTemplate->SetInternalFieldCount(3);
auto functionData = functionDataTemplate->NewInstance(getContext()).ToLocalChecked();
@ -1024,6 +1043,7 @@ void ScriptEngineV8::setObjectName(const QString& name) {
//V8TODO
bool ScriptEngineV8::setProperty(const char* name, const QVariant& value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Local<v8::Object> global = getContext()->Global();
auto v8Name = v8::String::NewFromUtf8(getIsolate(), name).ToLocalChecked();
V8ScriptValue v8Value = castVariantToValue(value);

View file

@ -175,7 +175,10 @@ public: // not for public use, but I don't like how Qt strings this along with p
v8::EscapableHandleScope handleScope(_v8Isolate);
return handleScope.Escape(_v8Context.Get(_v8Isolate));
}
const v8::Local<v8::Context> getConstContext() const {return _v8Context.Get(_v8Isolate);}
const v8::Local<v8::Context> getConstContext() const {
v8::EscapableHandleScope handleScope(_v8Isolate);
return handleScope.Escape(_v8Context.Get(_v8Isolate));
}
using ObjectWrapperMap = QMap<QObject*, QWeakPointer<ScriptObjectV8Proxy>>;
mutable QMutex _qobjectWrapperMapProtect;

View file

@ -198,6 +198,7 @@ void ScriptEngineV8::registerSystemTypes() {
}
int ScriptEngineV8::computeCastPenalty(const V8ScriptValue& v8Val, int destTypeId) {
v8::HandleScope handleScope(_v8Isolate);
const v8::Local<v8::Value> val = v8Val.constGet();
if (val->IsNumber()) {
switch (destTypeId){
@ -291,6 +292,7 @@ int ScriptEngineV8::computeCastPenalty(const V8ScriptValue& v8Val, int destTypeI
}
bool ScriptEngineV8::castValueToVariant(const V8ScriptValue& v8Val, QVariant& dest, int destTypeId) {
v8::HandleScope handleScope(_v8Isolate);
const v8::Local<v8::Value> val = v8Val.constGet();
// if we're not particularly interested in a specific type, try to detect if we're dealing with a registered type
@ -468,6 +470,8 @@ bool ScriptEngineV8::castValueToVariant(const V8ScriptValue& v8Val, QVariant& de
}
QString ScriptEngineV8::valueType(const V8ScriptValue& v8Val) {
// V8TODO
v8::HandleScope handleScope(const_cast<v8::Isolate*>(v8Val.constGetIsolate()));
const v8::Local<v8::Value> val = v8Val.constGet();
if (val->IsUndefined()) {

View file

@ -133,6 +133,8 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o
}
ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) {
//V8TODO This shouldn't cause problems but I'm not sure if it's ok
v8::HandleScope handleScope(const_cast<v8::Isolate*>(val.constGetIsolate()));
auto v8Value = val.constGet();
if (!v8Value->IsObject()) {
return nullptr;
@ -164,6 +166,8 @@ void ScriptObjectV8Proxy::investigate() {
Q_ASSERT(qobject);
if (!qobject) return;
v8::HandleScope handleScope(_engine->getIsolate());
auto objectTemplate = _v8ObjectTemplate.Get(_engine->getIsolate());
objectTemplate->SetInternalFieldCount(3);
objectTemplate->SetHandler(v8::NamedPropertyHandlerConfiguration(v8Get, v8Set));
@ -464,6 +468,8 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa
}
ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) {
// V8TODO
v8::HandleScope handleScope(const_cast<v8::Isolate*>(val.constGetIsolate()));
auto v8Value = val.constGet();
if (!v8Value->IsObject()) {
return nullptr;
@ -550,6 +556,8 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume
isolate->ThrowError("Referencing deleted native object");
return;
}
v8::HandleScope handleScope(_engine->getIsolate());
int scriptNumArgs = arguments.Length();
int numArgs = std::min(scriptNumArgs, _numMaxParms);
@ -898,6 +906,8 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu
if (id != 0 || call != QMetaObject::InvokeMetaMethod) {
return id;
}
v8::HandleScope handleScope(_engine->getIsolate());
//V8ScriptValueList args(isolate, v8::Null(isolate));
v8::Local<v8::Value> args[Q_METAMETHOD_INVOKE_MAX_ARGS];
@ -952,12 +962,14 @@ ScriptSignalV8Proxy::ConnectionList::iterator ScriptSignalV8Proxy::findConnectio
void ScriptSignalV8Proxy::connect(V8ScriptValue arg0, V8ScriptValue arg1) {
QObject* qobject = _object;
v8::Isolate *isolate = _engine->getIsolate();
if (!qobject) {
_engine->getIsolate()->ThrowError("Referencing deleted native object");
isolate->ThrowError("Referencing deleted native object");
return;
}
v8::HandleScope handleScope(isolate);
v8::Isolate *isolate = _engine->getIsolate();
// untangle the arguments
V8ScriptValue callback(isolate, v8::Null(isolate));
V8ScriptValue callbackThis(isolate, v8::Null(isolate));
@ -968,7 +980,7 @@ void ScriptSignalV8Proxy::connect(V8ScriptValue arg0, V8ScriptValue arg1) {
callback = arg0;
}
if (!callback.get()->IsFunction()) {
_engine->getIsolate()->ThrowError("Function expected as argument to 'connect'");
isolate->ThrowError("Function expected as argument to 'connect'");
return;
}
@ -1030,11 +1042,12 @@ void ScriptSignalV8Proxy::connect(V8ScriptValue arg0, V8ScriptValue arg1) {
void ScriptSignalV8Proxy::disconnect(V8ScriptValue arg0, V8ScriptValue arg1) {
QObject* qobject = _object;
v8::Isolate *isolate = _engine->getIsolate();
if (!qobject) {
_engine->getIsolate()->ThrowError("Referencing deleted native object");
isolate->ThrowError("Referencing deleted native object");
return;
}
v8::Isolate *isolate = _engine->getIsolate();
v8::HandleScope handleScope(isolate);
// untangle the arguments
V8ScriptValue callback(isolate, v8::Null(isolate));
@ -1046,7 +1059,7 @@ void ScriptSignalV8Proxy::disconnect(V8ScriptValue arg0, V8ScriptValue arg1) {
callback = arg0;
}
if (!callback.get()->IsFunction()) {
_engine->getIsolate()->ThrowError("Function expected as argument to 'disconnect'");
isolate->ThrowError("Function expected as argument to 'disconnect'");
return;
}

View file

@ -32,29 +32,32 @@ ScriptSyntaxCheckResultPointer ScriptProgramV8Wrapper::checkSyntax() {
}
bool ScriptProgramV8Wrapper::compile() {
auto isolate = _engine->getIsolate();
v8::HandleScope handleScope(isolate);
auto context = _engine->getContext();
int errorColumnNumber = 0;
int errorLineNumber = 0;
QString errorMessage = "";
QString errorBacktrace = "";
ScriptSyntaxCheckResult::State state;
v8::TryCatch tryCatch(_engine->getIsolate());
v8::ScriptOrigin scriptOrigin(_engine->getIsolate(), v8::String::NewFromUtf8(_engine->getIsolate(), _url.toStdString().c_str()).ToLocalChecked());
v8::TryCatch tryCatch(isolate);
v8::ScriptOrigin scriptOrigin(isolate, v8::String::NewFromUtf8(isolate, _url.toStdString().c_str()).ToLocalChecked());
v8::Local<v8::Script> script;
if (v8::Script::Compile(_engine->getContext(), v8::String::NewFromUtf8(_engine->getIsolate(), _source.toStdString().c_str()).ToLocalChecked(), &scriptOrigin).ToLocal(&script)) {
if (v8::Script::Compile(context, v8::String::NewFromUtf8(isolate, _source.toStdString().c_str()).ToLocalChecked(), &scriptOrigin).ToLocal(&script)) {
_compileResult = ScriptSyntaxCheckResultV8Wrapper(ScriptSyntaxCheckResult::Valid);
_value = V8ScriptProgram(_engine->getIsolate(), script);
_value = V8ScriptProgram(isolate, script);
return true;
}
v8::String::Utf8Value utf8Value(_engine->getIsolate(), tryCatch.Exception());
v8::String::Utf8Value utf8Value(isolate, tryCatch.Exception());
errorMessage = QString(*utf8Value);
v8::Local<v8::Message> exceptionMessage = tryCatch.Message();
if (!exceptionMessage.IsEmpty()) {
errorLineNumber = exceptionMessage->GetLineNumber(_engine->getContext()).FromJust();
errorColumnNumber = exceptionMessage->GetStartColumn(_engine->getContext()).FromJust();
errorLineNumber = exceptionMessage->GetLineNumber(context).FromJust();
errorColumnNumber = exceptionMessage->GetStartColumn(context).FromJust();
v8::Local<v8::Value> backtraceV8String;
if (tryCatch.StackTrace(_engine->getContext()).ToLocal(&backtraceV8String) && backtraceV8String->IsString() &&
if (tryCatch.StackTrace(context).ToLocal(&backtraceV8String) && backtraceV8String->IsString() &&
v8::Local<v8::String>::Cast(backtraceV8String)->Length() > 0) {
v8::String::Utf8Value backtraceUtf8Value(_engine->getIsolate(), backtraceV8String);
v8::String::Utf8Value backtraceUtf8Value(isolate, backtraceV8String);
errorBacktrace = *backtraceUtf8Value;
}
}

View file

@ -14,15 +14,17 @@
#include "ScriptValueIteratorV8Wrapper.h"
V8ScriptValueIterator::V8ScriptValueIterator(ScriptEngineV8* engine, v8::Local<v8::Value> object) : _engine(engine) {
_context.Reset(_engine->getIsolate(), _engine->getContext());
auto context = _context.Get(_engine->getIsolate());
auto isolate = _engine->getIsolate();
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);
}
_object.Reset(_engine->getIsolate(), v8Object);
_propertyNames.Reset(_engine->getIsolate(), v8Object->GetOwnPropertyNames(context).ToLocalChecked());
_length = _propertyNames.Get(_engine->getIsolate())->Length();
_object.Reset(isolate, v8Object);
_propertyNames.Reset(isolate, v8Object->GetOwnPropertyNames(context).ToLocalChecked());
_length = _propertyNames.Get(isolate)->Length();
_currentIndex = 0;
}
@ -31,12 +33,14 @@ bool V8ScriptValueIterator::hasNext() const {
}
QString V8ScriptValueIterator::name() const {
auto context = _context.Get(_engine->getIsolate());
auto isolate = _engine->getIsolate();
v8::HandleScope handleScope(isolate);
auto context = _context.Get(isolate);
v8::Local<v8::Value> propertyName;
if (!_propertyNames.Get(_engine->getIsolate())->Get(context, _length).ToLocal(&propertyName)) {
if (!_propertyNames.Get(isolate)->Get(context, _length).ToLocal(&propertyName)) {
Q_ASSERT(false);
}
return QString(*v8::String::Utf8Value(_engine->getIsolate(), propertyName));
return QString(*v8::String::Utf8Value(isolate, propertyName));
}
void V8ScriptValueIterator::next() {
@ -46,16 +50,18 @@ void V8ScriptValueIterator::next() {
}
V8ScriptValue V8ScriptValueIterator::value() {
auto context = _context.Get(_engine->getIsolate());
auto isolate = _engine->getIsolate();
v8::HandleScope handleScope(isolate);
auto context = _context.Get(isolate);
v8::Local<v8::Value> v8Value;
v8::Local<v8::Value> propertyName;
if (!_propertyNames.Get(_engine->getIsolate())->Get(context, _length).ToLocal(&propertyName)) {
if (!_propertyNames.Get(isolate)->Get(context, _length).ToLocal(&propertyName)) {
Q_ASSERT(false);
}
if (!_object.Get(_engine->getIsolate())->Get(context, propertyName->ToString(context).ToLocalChecked()).ToLocal(&v8Value)) {
if (!_object.Get(isolate)->Get(context, propertyName->ToString(context).ToLocalChecked()).ToLocal(&v8Value)) {
Q_ASSERT(false);
}
return V8ScriptValue(_engine->getIsolate(), v8Value);
return V8ScriptValue(isolate, v8Value);
}
ScriptValue::PropertyFlags ScriptValueIteratorV8Wrapper::flags() const {

View file

@ -60,6 +60,7 @@ V8ScriptValue ScriptValueV8Wrapper::fullUnwrap(ScriptEngineV8* engine, const Scr
}
ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const ScriptValueList& args) {
v8::HandleScope handleScope(_engine->getIsolate());
V8ScriptValue v8This = fullUnwrap(thisObject);
//V8ScriptValueList qArgs;
Q_ASSERT(args.length() <= Q_METAMETHOD_INVOKE_MAX_ARGS);
@ -84,6 +85,7 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
}
ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const ScriptValue& arguments) {
v8::HandleScope handleScope(_engine->getIsolate());
V8ScriptValue v8This = fullUnwrap(thisObject);
V8ScriptValue v8Args = fullUnwrap(arguments);
// V8TODO should there be a v8 try-catch here?
@ -104,6 +106,7 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
}
ScriptValue ScriptValueV8Wrapper::construct(const ScriptValueList& args) {
v8::HandleScope handleScope(_engine->getIsolate());
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];
@ -126,6 +129,7 @@ ScriptValue ScriptValueV8Wrapper::construct(const ScriptValueList& args) {
}
ScriptValue ScriptValueV8Wrapper::construct(const ScriptValue& arguments) {
v8::HandleScope handleScope(_engine->getIsolate());
// V8TODO I'm not sure in what format arguments are yet, backtrace will show how it is used
Q_ASSERT(false);
return _engine->undefinedValue();
@ -153,6 +157,7 @@ ScriptValueIteratorPointer ScriptValueV8Wrapper::newIterator() const {
}
ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValue::ResolveFlags& mode) const {
v8::HandleScope handleScope(_engine->getIsolate());
if (!_value.constGet()->IsObject()) {
//V8TODO: what about flags?
v8::Local<v8::Value> resultLocal;
@ -171,6 +176,7 @@ ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValu
}
ScriptValue ScriptValueV8Wrapper::property(quint32 arrayIndex, const ScriptValue::ResolveFlags& mode) const {
v8::HandleScope handleScope(_engine->getIsolate());
if (!_value.constGet()->IsObject()) {
//V8TODO: what about flags?
v8::Local<v8::Value> resultLocal;
@ -191,6 +197,7 @@ void ScriptValueV8Wrapper::setData(const ScriptValue& value) {
}
void ScriptValueV8Wrapper::setProperty(const QString& name, const ScriptValue& value, const ScriptValue::PropertyFlags& flags) {
v8::HandleScope handleScope(_engine->getIsolate());
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();
@ -237,47 +244,65 @@ void ScriptValueV8Wrapper::setPrototype(const ScriptValue& prototype) {
}
bool ScriptValueV8Wrapper::strictlyEquals(const ScriptValue& other) const {
v8::HandleScope handleScope(_engine->getIsolate());
ScriptValueV8Wrapper* unwrappedOther = unwrap(other);
return unwrappedOther ? _value.constGet()->StrictEquals(unwrappedOther->toV8Value().constGet()) : false;
}
bool ScriptValueV8Wrapper::toBool() const {
v8::HandleScope handleScope(_engine->getIsolate());
return _value.constGet()->ToBoolean(_engine->getIsolate())->Value();
}
qint32 ScriptValueV8Wrapper::toInt32() const {
v8::HandleScope handleScope(_engine->getIsolate());
v8::Local<v8::Integer> *integer;
Q_ASSERT(_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer));
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) {
Q_ASSERT(false);
}
return static_cast<int32_t>((*integer)->Value());
}
double ScriptValueV8Wrapper::toInteger() const {
v8::HandleScope handleScope(_engine->getIsolate());
v8::Local<v8::Integer> *integer;
Q_ASSERT(_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer));
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) {
Q_ASSERT(false);
}
return (*integer)->Value();
}
double ScriptValueV8Wrapper::toNumber() const {
v8::HandleScope handleScope(_engine->getIsolate());
v8::Local<v8::Number> *number;
Q_ASSERT(_value.constGet()->ToNumber(_value.constGetContext()).ToLocal(number));
if (!_value.constGet()->ToNumber(_value.constGetContext()).ToLocal(number)) {
Q_ASSERT(false);
}
return (*number)->Value();
}
QString ScriptValueV8Wrapper::toString() const {
v8::HandleScope handleScope(_engine->getIsolate());
v8::String::Utf8Value string(_engine->getIsolate(), _value.constGet());
Q_ASSERT(*string != nullptr);
return QString(*string);
}
quint16 ScriptValueV8Wrapper::toUInt16() const {
v8::HandleScope handleScope(_engine->getIsolate());
v8::Local<v8::Uint32> *integer;
Q_ASSERT(_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer));
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) {
Q_ASSERT(false);
}
return static_cast<uint16_t>((*integer)->Value());
}
quint32 ScriptValueV8Wrapper::toUInt32() const {
v8::HandleScope handleScope(_engine->getIsolate());
v8::Local<v8::Uint32> *integer;
Q_ASSERT(_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer));
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) {
Q_ASSERT(false);
}
return (*integer)->Value();
}
@ -302,6 +327,7 @@ QObject* ScriptValueV8Wrapper::toQObject() const {
}
bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const {
v8::HandleScope handleScope(_engine->getIsolate());
ScriptValueV8Wrapper* unwrappedOther = unwrap(other);
//V8TODO: does this work with different contexts/isolates?
// in such case conversion will probably be necessary

View file

@ -24,13 +24,23 @@ 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), _context(isolate, isolate->GetCurrentContext()) {
V8ScriptValueTemplate(v8::Isolate *isolate, const v8::Local<T> value) : _isolate(isolate) {
//_value.reset(_isolate, value);
v8::HandleScope handleScope(_isolate);
_context.Reset(isolate, isolate->GetCurrentContext());
_value.reset(new v8::UniquePersistent<T>(_isolate, std::move(value)));
};
v8::Local<T> get() {return _value.get()->Get(_isolate);};
const v8::Local<T> constGet() const {return _value.get()->Get(_isolate);};
V8ScriptValueTemplate<T>&& copy() const {return new V8ScriptValueTemplate(_isolate, v8::Local<T>::New(_isolate, constGet()));};
v8::Local<T> get() {
v8::EscapableHandleScope handleScope(_isolate);
return _value.get()->Get(_isolate);
};
const v8::Local<T> constGet() const {
v8::EscapableHandleScope handleScope(_isolate);
return _value.get()->Get(_isolate);
};
V8ScriptValueTemplate<T>&& copy() const {
v8::HandleScope handleScope(_isolate);
return new V8ScriptValueTemplate(_isolate, v8::Local<T>::New(_isolate, constGet()));};
const v8::Local<v8::Context> constGetContext() const {
v8::EscapableHandleScope handleScope(_isolate);
return handleScope.Escape(_context.Get(_isolate));