mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 04:42:20 +02:00
V8 fixes
This commit is contained in:
parent
f65e72c8f2
commit
5cf32a968c
14 changed files with 142 additions and 17 deletions
|
@ -1,4 +1,4 @@
|
|||
'use strict';
|
||||
'no use strict';
|
||||
//
|
||||
// activator-doppleganger.js
|
||||
//
|
||||
|
@ -23,6 +23,8 @@
|
|||
autoUpdate: true
|
||||
});
|
||||
|
||||
// V8TODO: does this need to be fixed? Right now it refers to global object in non-strict mode,
|
||||
// and in strict mode it's undefined
|
||||
this.preload = function(entityID) {
|
||||
thisEntityID = entityID;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ WindowScriptingInterface::~WindowScriptingInterface() {
|
|||
}
|
||||
|
||||
ScriptValue WindowScriptingInterface::hasFocus() {
|
||||
Q_ASSERT(engine);
|
||||
return engine()->newValue(qApp->hasFocus());
|
||||
}
|
||||
|
||||
|
@ -105,6 +106,7 @@ void WindowScriptingInterface::alert(const QString& message) {
|
|||
/// \param const QString& message message to display
|
||||
/// \return ScriptValue `true` if 'Yes' was clicked, `false` otherwise
|
||||
ScriptValue WindowScriptingInterface::confirm(const QString& message) {
|
||||
Q_ASSERT(engine);
|
||||
return engine()->newValue((QMessageBox::Yes == OffscreenUi::question("", message, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)));
|
||||
}
|
||||
|
||||
|
@ -114,6 +116,7 @@ ScriptValue WindowScriptingInterface::confirm(const QString& message) {
|
|||
/// \return ScriptValue string text value in text box if the dialog was accepted, `null` otherwise.
|
||||
ScriptValue WindowScriptingInterface::prompt(const QString& message, const QString& defaultText) {
|
||||
QString result = OffscreenUi::getText(nullptr, "", message, QLineEdit::Normal, defaultText);
|
||||
Q_ASSERT(engine);
|
||||
auto sResult = engine()->newValue(result);
|
||||
if (sResult.equals(engine()->newValue(""))) {
|
||||
return engine()->nullValue();
|
||||
|
@ -232,6 +235,7 @@ ScriptValue WindowScriptingInterface::browseDir(const QString& title, const QStr
|
|||
if (!result.isEmpty()) {
|
||||
setPreviousBrowseLocation(QFileInfo(result).absolutePath());
|
||||
}
|
||||
Q_ASSERT(engine);
|
||||
return result.isEmpty() ? engine()->nullValue() : engine()->newValue(result);
|
||||
}
|
||||
|
||||
|
@ -276,6 +280,7 @@ ScriptValue WindowScriptingInterface::browse(const QString& title, const QString
|
|||
if (!result.isEmpty()) {
|
||||
setPreviousBrowseLocation(QFileInfo(result).absolutePath());
|
||||
}
|
||||
Q_ASSERT(engine);
|
||||
return result.isEmpty() ? engine()->nullValue() : engine()->newValue(result);
|
||||
}
|
||||
|
||||
|
@ -323,6 +328,7 @@ ScriptValue WindowScriptingInterface::save(const QString& title, const QString&
|
|||
if (!result.isEmpty()) {
|
||||
setPreviousBrowseLocation(QFileInfo(result).absolutePath());
|
||||
}
|
||||
Q_ASSERT(engine);
|
||||
return result.isEmpty() ? engine()->nullValue() : engine()->newValue(result);
|
||||
}
|
||||
|
||||
|
@ -373,6 +379,7 @@ ScriptValue WindowScriptingInterface::browseAssets(const QString& title, const Q
|
|||
if (!result.isEmpty()) {
|
||||
setPreviousBrowseAssetLocation(QFileInfo(result).absolutePath());
|
||||
}
|
||||
Q_ASSERT(engine);
|
||||
return result.isEmpty() ? engine()->nullValue() : engine()->newValue(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -2557,6 +2557,7 @@ QDataStream& operator>>(QDataStream& in, AttachmentData& attachment) {
|
|||
void AttachmentDataObject::setModelURL(const QString& modelURL) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.modelURL = modelURL;
|
||||
Q_ASSERT(engine);
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
|
@ -2567,6 +2568,7 @@ QString AttachmentDataObject::getModelURL() const {
|
|||
void AttachmentDataObject::setJointName(const QString& jointName) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.jointName = jointName;
|
||||
Q_ASSERT(engine);
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
|
@ -2577,6 +2579,7 @@ QString AttachmentDataObject::getJointName() const {
|
|||
void AttachmentDataObject::setTranslation(const glm::vec3& translation) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.translation = translation;
|
||||
Q_ASSERT(engine);
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
|
@ -2587,6 +2590,7 @@ glm::vec3 AttachmentDataObject::getTranslation() const {
|
|||
void AttachmentDataObject::setRotation(const glm::quat& rotation) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.rotation = rotation;
|
||||
Q_ASSERT(engine);
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
|
@ -2597,6 +2601,7 @@ glm::quat AttachmentDataObject::getRotation() const {
|
|||
void AttachmentDataObject::setScale(float scale) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.scale = scale;
|
||||
Q_ASSERT(engine);
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
|
@ -2607,6 +2612,7 @@ float AttachmentDataObject::getScale() const {
|
|||
void AttachmentDataObject::setIsSoft(bool isSoft) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.isSoft = isSoft;
|
||||
Q_ASSERT(engine);
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ void AssetScriptingInterface::uploadData(QString data, const ScriptValue& callba
|
|||
auto upload = DependencyManager::get<AssetClient>()->createUpload(dataByteArray);
|
||||
|
||||
Promise deferred = makePromise(__FUNCTION__);
|
||||
Q_ASSERT(engine);
|
||||
auto scriptEngine = engine();
|
||||
deferred->ready([=](QString error, QVariantMap result) {
|
||||
auto url = result.value("url").toString();
|
||||
|
@ -96,6 +97,7 @@ void AssetScriptingInterface::setMapping(QString path, QString hash, const Scrip
|
|||
auto handler = jsBindCallback(thisObject(), callback);
|
||||
auto setMappingRequest = assetClient()->createSetMappingRequest(path, hash);
|
||||
Promise deferred = makePromise(__FUNCTION__);
|
||||
Q_ASSERT(engine);
|
||||
auto scriptEngine = engine();
|
||||
deferred->ready([=](QString error, QVariantMap result) {
|
||||
jsCallback(handler, scriptEngine->newValue(error), result);
|
||||
|
@ -133,6 +135,7 @@ void AssetScriptingInterface::downloadData(QString urlString, const ScriptValue&
|
|||
auto assetRequest = assetClient->createRequest(hash);
|
||||
|
||||
Promise deferred = makePromise(__FUNCTION__);
|
||||
Q_ASSERT(engine);
|
||||
auto scriptEngine = engine();
|
||||
deferred->ready([=](QString error, QVariantMap result) {
|
||||
// FIXME: to remain backwards-compatible the signature here is "callback(data, n/a)"
|
||||
|
@ -196,6 +199,7 @@ void AssetScriptingInterface::getMapping(QString asset, const ScriptValue& callb
|
|||
JS_VERIFY(AssetUtils::isValidFilePath(path), "invalid ATP file path: " + asset + "(path:"+path+")");
|
||||
JS_VERIFY(callback.isFunction(), "expected second parameter to be a callback function");
|
||||
Promise promise = getAssetInfo(path);
|
||||
Q_ASSERT(engine);
|
||||
auto scriptEngine = engine();
|
||||
promise->ready([=](QString error, QVariantMap result) {
|
||||
jsCallback(handler, scriptEngine->newValue(error), scriptEngine->newValue(result.value("hash").toString()));
|
||||
|
@ -229,6 +233,7 @@ Promise AssetScriptingInterface::jsPromiseReady(Promise promise, const ScriptVal
|
|||
if (!jsVerify(handler.isValid(), "jsPromiseReady -- invalid callback handler")) {
|
||||
return nullptr;
|
||||
}
|
||||
Q_ASSERT(engine);
|
||||
auto scriptEngine = engine();
|
||||
return promise->ready([this, handler, scriptEngine](QString error, QVariantMap result) {
|
||||
jsCallback(handler, scriptEngine->newValue(error), result);
|
||||
|
@ -238,6 +243,7 @@ Promise AssetScriptingInterface::jsPromiseReady(Promise promise, const ScriptVal
|
|||
void AssetScriptingInterface::jsCallback(const ScriptValue& handler,
|
||||
const ScriptValue& error, const ScriptValue& result) {
|
||||
Q_ASSERT(thread() == QThread::currentThread());
|
||||
Q_ASSERT(engine);
|
||||
auto errorValue = !error.toBool() ? engine()->nullValue() : error;
|
||||
JS_VERIFY(handler.isObject() && handler.property("callback").isFunction(),
|
||||
QString("jsCallback -- .callback is not a function (%1)")
|
||||
|
@ -536,6 +542,7 @@ void AssetScriptingInterface::loadFromCache(const ScriptValue& options, const Sc
|
|||
}
|
||||
|
||||
bool AssetScriptingInterface::canWriteCacheValue(const QUrl& url) {
|
||||
Q_ASSERT(engine);
|
||||
auto scriptManager = engine()->manager();
|
||||
if (!scriptManager) {
|
||||
return false;
|
||||
|
|
|
@ -80,12 +80,14 @@ ScriptValue ConsoleScriptingInterface::exception(ScriptContext* context, ScriptE
|
|||
void ConsoleScriptingInterface::time(QString labelName) {
|
||||
_timerDetails.insert(labelName, QDateTime::currentDateTime().toUTC());
|
||||
QString message = QString("%1: Timer started").arg(labelName);
|
||||
Q_ASSERT(engine);
|
||||
if (ScriptManager* scriptManager = engine()->manager()) {
|
||||
scriptManager->scriptPrintedMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleScriptingInterface::timeEnd(QString labelName) {
|
||||
Q_ASSERT(engine);
|
||||
if (ScriptManager* scriptManager = engine()->manager()) {
|
||||
if (!_timerDetails.contains(labelName)) {
|
||||
scriptManager->scriptErrorMessage("No such label found " + labelName);
|
||||
|
@ -134,6 +136,7 @@ ScriptValue ConsoleScriptingInterface::assertion(ScriptContext* context, ScriptE
|
|||
}
|
||||
|
||||
void ConsoleScriptingInterface::trace() {
|
||||
Q_ASSERT(engine);
|
||||
ScriptEnginePointer scriptEngine = engine();
|
||||
if (ScriptManager* scriptManager = scriptEngine->manager()) {
|
||||
scriptManager->scriptPrintedMessage
|
||||
|
@ -143,6 +146,7 @@ void ConsoleScriptingInterface::trace() {
|
|||
}
|
||||
|
||||
void ConsoleScriptingInterface::clear() {
|
||||
Q_ASSERT(engine);
|
||||
if (ScriptManager* scriptManager = engine()->manager()) {
|
||||
scriptManager->clearDebugLogWindow();
|
||||
}
|
||||
|
|
|
@ -88,6 +88,7 @@ void Mat4::print(const QString& label, const glm::mat4& m, bool transpose) const
|
|||
QString message = QString("%1 %2").arg(qPrintable(label));
|
||||
message = message.arg(glm::to_string(out).c_str());
|
||||
qCDebug(scriptengine) << message;
|
||||
Q_ASSERT(engine);
|
||||
if (ScriptManager* scriptManager = engine()->manager()) {
|
||||
scriptManager->print(message);
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ void Quat::print(const QString& label, const glm::quat& q, bool asDegrees) {
|
|||
message = message.arg(glm::to_string(glm::dquat(q)).c_str());
|
||||
}
|
||||
qCDebug(scriptengine) << message;
|
||||
Q_ASSERT(engine);
|
||||
if (ScriptManager* scriptManager = engine()->manager()) {
|
||||
scriptManager->print(message);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ void ScriptUUID::print(const QString& label, const QUuid& id) {
|
|||
QString message = QString("%1 %2").arg(qPrintable(label));
|
||||
message = message.arg(id.toString());
|
||||
qCDebug(scriptengine) << message;
|
||||
Q_ASSERT(engine);
|
||||
if (ScriptManager* scriptManager = engine()->manager()) {
|
||||
scriptManager->print(message);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ void Vec3::print(const QString& label, const glm::vec3& v) {
|
|||
QString message = QString("%1 %2").arg(qPrintable(label));
|
||||
message = message.arg(glm::to_string(glm::dvec3(v)).c_str());
|
||||
qCDebug(scriptengine) << message;
|
||||
Q_ASSERT(engine);
|
||||
if (ScriptManager* scriptManager = engine()->manager()) {
|
||||
scriptManager->print(message);
|
||||
}
|
||||
|
|
|
@ -427,7 +427,6 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
|
|||
v8::Context::Scope contextScope(context);
|
||||
_contexts.append(std::make_shared<ScriptContextV8Wrapper>(this,context, ScriptContextPointer()));
|
||||
|
||||
|
||||
V8ScriptValue nullScriptValue(this, v8::Null(_v8Isolate));
|
||||
_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, nullScriptValue));
|
||||
|
||||
|
@ -802,6 +801,32 @@ const v8::Local<v8::Context> ScriptEngineV8::getConstContext() const {
|
|||
Q_ASSERT(!_contexts.isEmpty());
|
||||
return handleScope.Escape(_contexts.last().get()->toV8Value());
|
||||
}
|
||||
|
||||
// Stored objects are used to create global objects for evaluateInClosure
|
||||
void ScriptEngineV8::storeGlobalObjectContents() {
|
||||
if (areGlobalObjectContentsStored) {
|
||||
return;
|
||||
}
|
||||
v8::Locker locker(_v8Isolate);
|
||||
v8::Isolate::Scope isolateScope(_v8Isolate);
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
auto context = getContext();
|
||||
v8::Context::Scope contextScope(context);
|
||||
v8::Local<v8::Object> globalMemberObjects = v8::Object::New(_v8Isolate);
|
||||
|
||||
auto globalMemberNames = context->Global()->GetPropertyNames(context).ToLocalChecked();
|
||||
for (size_t i = 0; i < globalMemberNames->Length(); i++) {
|
||||
auto name = globalMemberNames->Get(context, i).ToLocalChecked();
|
||||
if(!globalMemberObjects->Set(context, name, context->Global()->Get(context, name).ToLocalChecked()).FromMaybe(false)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
_globalObjectContents.Reset(_v8Isolate, globalMemberObjects);
|
||||
qDebug() << "ScriptEngineV8::storeGlobalObjectContents: " << globalMemberNames->Length() << " objects stored";
|
||||
areGlobalObjectContentsStored = true;
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
||||
const ScriptProgramPointer& _program) {
|
||||
PROFILE_RANGE(script, "evaluateInClosure");
|
||||
|
@ -812,6 +837,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
v8::Locker locker(_v8Isolate);
|
||||
v8::Isolate::Scope isolateScope(_v8Isolate);
|
||||
v8::HandleScope handleScope(_v8Isolate);
|
||||
storeGlobalObjectContents();
|
||||
|
||||
v8::Local<v8::Object> closureObject;
|
||||
//v8::Local<v8::Value> oldGlobal;
|
||||
|
@ -896,6 +922,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
if (!unwrappedProgram->compile()) {
|
||||
qDebug(scriptengine) << "Can't compile script for evaluating in closure";
|
||||
Q_ASSERT(false);
|
||||
popContext();
|
||||
return nullValue();
|
||||
}
|
||||
const V8ScriptProgram& program = unwrappedProgram->toV8Value();
|
||||
|
@ -928,18 +955,35 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
|
|||
{
|
||||
v8::TryCatch tryCatch(getIsolate());
|
||||
// Since V8 cannot use arbitrary object as global object, objects from main global need to be copied to closure's global object
|
||||
auto oldGlobalMemberNames = oldContext->Global()->GetPropertyNames(oldContext).ToLocalChecked();
|
||||
for (size_t i = 0; i < oldGlobalMemberNames->Length(); i++) {
|
||||
auto name = oldGlobalMemberNames->Get(closureContext, i).ToLocalChecked();
|
||||
if(!closureContext->Global()->Set(closureContext, name, oldContext->Global()->Get(oldContext, name).ToLocalChecked()).FromMaybe(false)) {
|
||||
auto globalObjectContents = _globalObjectContents.Get(_v8Isolate);
|
||||
auto globalMemberNames = globalObjectContents->GetPropertyNames(globalObjectContents->CreationContext()).ToLocalChecked();
|
||||
for (size_t i = 0; i < globalMemberNames->Length(); i++) {
|
||||
auto name = globalMemberNames->Get(closureContext, i).ToLocalChecked();
|
||||
if(!closureContext->Global()->Set(closureContext, name, globalObjectContents->Get(globalObjectContents->CreationContext(), name).ToLocalChecked()).FromMaybe(false)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}
|
||||
qDebug() << "ScriptEngineV8::evaluateInClosure: " << globalMemberNames->Length() << " objects added to global";
|
||||
|
||||
/*auto oldGlobalMemberNames = oldContext->Global()->GetPropertyNames(oldContext).ToLocalChecked();
|
||||
//auto oldGlobalMemberNames = oldContext->Global()->GetPropertyNames(closureContext).ToLocalChecked();
|
||||
for (size_t i = 0; i < oldGlobalMemberNames->Length(); i++) {
|
||||
auto name = oldGlobalMemberNames->Get(closureContext, i).ToLocalChecked();
|
||||
//auto name = oldGlobalMemberNames->Get(oldContext, i).ToLocalChecked();
|
||||
if(!closureContext->Global()->Set(closureContext, name, oldContext->Global()->Get(oldContext, name).ToLocalChecked()).FromMaybe(false)) {
|
||||
//if(!closureContext->Global()->Set(closureContext, name, oldContext->Global()->Get(closureContext, name).ToLocalChecked()).FromMaybe(false)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}*/
|
||||
// Objects from closure need to be copied to global object too
|
||||
// V8TODO: I'm not sure which context to use with Get
|
||||
auto closureMemberNames = closureObject->GetPropertyNames(closureContext).ToLocalChecked();
|
||||
//auto closureMemberNames = closureObject->GetPropertyNames(oldContext).ToLocalChecked();
|
||||
for (size_t i = 0; i < closureMemberNames->Length(); i++) {
|
||||
auto name = closureMemberNames->Get(closureContext, i).ToLocalChecked();
|
||||
//auto name = closureMemberNames->Get(oldContext, i).ToLocalChecked();
|
||||
if(!closureContext->Global()->Set(closureContext, name, closureObject->Get(closureContext, name).ToLocalChecked()).FromMaybe(false)) {
|
||||
//if(!closureContext->Global()->Set(closureContext, name, closureObject->Get(oldContext, name).ToLocalChecked()).FromMaybe(false)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
@ -1455,6 +1499,7 @@ ScriptContext* ScriptEngineV8::currentContext() const {
|
|||
// I'm not sure how to do this without discarding const
|
||||
_currContext = std::make_shared<ScriptContextV8Wrapper>(const_cast<ScriptEngineV8*>(this));
|
||||
}*/
|
||||
// V8TODO: add FunctionCallbackInfo or PropertyCallbackInfo when necessary
|
||||
return _contexts.last().get();
|
||||
}
|
||||
|
||||
|
@ -1501,7 +1546,7 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int
|
|||
ScriptEngineV8 *scriptEngine = reinterpret_cast<ScriptEngineV8*>
|
||||
(object->GetAlignedPointerFromInternalField(1));
|
||||
ScriptContextV8Wrapper scriptContext(scriptEngine, &info, scriptEngine->getContext(), scriptEngine->currentContext()->parentContext());
|
||||
//V8TODO: this scriptContext needs to have FunctionCallbackInfo added
|
||||
ScriptContextGuard scriptContextGuard(&scriptContext);
|
||||
ScriptValue result = function(&scriptContext, scriptEngine);
|
||||
ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result);
|
||||
if (unwrapped) {
|
||||
|
|
|
@ -202,6 +202,8 @@ public: // not for public use, but I don't like how Qt strings this along with p
|
|||
|
||||
ScriptContextV8Pointer pushContext(v8::Local<v8::Context> context);
|
||||
void popContext();
|
||||
// V8TODO: call this after initializing global object
|
||||
void storeGlobalObjectContents();
|
||||
|
||||
protected:
|
||||
// like `newFunction`, but allows mapping inline C++ lambdas with captures as callable V8ScriptValues
|
||||
|
@ -240,6 +242,8 @@ protected:
|
|||
//mutable ScriptContextV8Pointer _currContext;
|
||||
// Current context stack. Main context is first on the list and current one is last.
|
||||
QList<ScriptContextV8Pointer> _contexts;
|
||||
v8::Persistent<v8::Object> _globalObjectContents;
|
||||
bool areGlobalObjectContentsStored {false};
|
||||
|
||||
//V8TODO
|
||||
//ArrayBufferClass* _arrayBufferClass;
|
||||
|
|
|
@ -39,9 +39,9 @@ static const void *internalPointsToMethodProxy = (void *)0x13373000;
|
|||
|
||||
// Used strictly to replace the "this" object value for property access. May expand to a full context element
|
||||
// if we find it necessary to, but hopefully not needed
|
||||
class ScriptPropertyContextQtWrapper final : public ScriptContext {
|
||||
class ScriptPropertyContextV8Wrapper final : public ScriptContext {
|
||||
public: // construction
|
||||
inline ScriptPropertyContextQtWrapper(const ScriptValue& object, ScriptContext* parentContext) :
|
||||
inline ScriptPropertyContextV8Wrapper(const ScriptValue& object, ScriptContext* parentContext) :
|
||||
_parent(parentContext), _object(object) {}
|
||||
|
||||
public: // ScriptContext implementation
|
||||
|
@ -568,7 +568,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
|
|||
|
||||
QMetaProperty prop = metaObject->property(propId);
|
||||
ScriptValue scriptThis = ScriptValue(new ScriptValueV8Wrapper(_engine, object));
|
||||
ScriptPropertyContextQtWrapper ourContext(scriptThis, _engine->currentContext());
|
||||
ScriptPropertyContextV8Wrapper ourContext(scriptThis, _engine->currentContext());
|
||||
ScriptContextGuard guard(&ourContext);
|
||||
|
||||
QVariant varValue = prop.read(qobject);
|
||||
|
@ -611,7 +611,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
|
|||
ScriptEngine::QObjectWrapOptions options = ScriptEngine::ExcludeSuperClassContents |
|
||||
//V8TODO ScriptEngine::ExcludeDeleteLater |
|
||||
ScriptEngine::PreferExistingWrapperObject;
|
||||
//V8TODO: why is it returning new object every time?
|
||||
// It's not necessarily new, newQObject looks for it first in object wrapper map
|
||||
return ScriptObjectV8Proxy::newQObject(_engine, proxy, ScriptEngine::ScriptOwnership, options);
|
||||
//return _engine->newQObject(proxy, ScriptEngine::ScriptOwnership, options);
|
||||
}
|
||||
|
@ -642,7 +642,7 @@ void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptStrin
|
|||
QMetaProperty prop = metaObject->property(propId);
|
||||
|
||||
ScriptValue scriptThis = ScriptValue(new ScriptValueV8Wrapper(_engine, object));
|
||||
ScriptPropertyContextQtWrapper ourContext(scriptThis, _engine->currentContext());
|
||||
ScriptPropertyContextV8Wrapper ourContext(scriptThis, _engine->currentContext());
|
||||
ScriptContextGuard guard(&ourContext);
|
||||
|
||||
int propTypeId = prop.userType();
|
||||
|
@ -883,8 +883,10 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume
|
|||
}
|
||||
|
||||
if (isValidMetaSelected) {
|
||||
//ScriptContextV8Wrapper ourContext(_engine, context);
|
||||
//ScriptContextGuard guard(&ourContext);
|
||||
// V8TODO: is this the correct wrapper?
|
||||
ScriptContextV8Wrapper ourContext(_engine, &arguments, _engine->getContext(),
|
||||
_engine->currentContext()->parentContext());
|
||||
ScriptContextGuard guard(&ourContext);
|
||||
const QMetaMethod& meta = _metas[bestMeta];
|
||||
int returnTypeId = meta.returnType();
|
||||
QVector <QGenericArgument> &qGenArgs = qGenArgsVectors[bestMeta];
|
||||
|
@ -1333,8 +1335,15 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) {
|
|||
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;
|
||||
auto destFunctionContext = destFunction->CreationContext();
|
||||
// V8TODO: I'm not sure which context to use here
|
||||
//auto destFunctionContext = destFunction->CreationContext();
|
||||
auto destFunctionContext = _engine->getContext();
|
||||
Q_ASSERT(thisObject().isObject());
|
||||
V8ScriptValue v8ThisObject = ScriptValueV8Wrapper::fullUnwrap(_engine, thisObject());
|
||||
Q_ASSERT(ScriptObjectV8Proxy::unwrapProxy(v8ThisObject));
|
||||
ScriptSignalV8Proxy* thisProxy = dynamic_cast<ScriptSignalV8Proxy*>(ScriptObjectV8Proxy::unwrapProxy(v8ThisObject)->toQObject());
|
||||
Q_ASSERT(thisProxy);
|
||||
qDebug(scriptengine) << "ScriptSignalV8Proxy::connect: " << thisProxy->fullName() << " fullName: " << fullName();
|
||||
//Q_ASSERT(destFunction->InternalFieldCount() == 4);
|
||||
//Q_ASSERT(destData.get()->IsArray());
|
||||
//v8::Local<v8::Value> destData = destFunction->GetInternalField(3);
|
||||
|
@ -1344,15 +1353,27 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) {
|
|||
if (destData->IsArray()) {
|
||||
v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData);
|
||||
int length = destArray->Length();//destData.property("length").toInteger();
|
||||
// V8TODO: Maybe copying array is unnecessary?
|
||||
v8::Local<v8::Array> newArray = v8::Array::New(isolate, length + 1);
|
||||
bool foundIt = false;
|
||||
for (int idx = 0; idx < length && !foundIt; ++idx) {
|
||||
v8::Local<v8::Value> entry = destArray->Get(destFunctionContext, idx).ToLocalChecked();
|
||||
{
|
||||
qDebug() << "ScriptSignalV8Proxy::connect: entry details: " << _engine->scriptValueDebugDetailsV8(V8ScriptValue(_engine, entry));
|
||||
Q_ASSERT(entry->IsObject());
|
||||
V8ScriptValue v8EntryObject(_engine, entry);
|
||||
Q_ASSERT(ScriptObjectV8Proxy::unwrapProxy(v8EntryObject));
|
||||
// For debugging
|
||||
ScriptSignalV8Proxy* entryProxy = dynamic_cast<ScriptSignalV8Proxy*>(ScriptObjectV8Proxy::unwrapProxy(v8EntryObject)->toQObject());
|
||||
Q_ASSERT(thisProxy);
|
||||
qDebug(scriptengine) << "ScriptSignalV8Proxy::connect: entry proxy: " << entryProxy->fullName();
|
||||
}
|
||||
if (!newArray->Set(destFunctionContext, idx, entry).FromMaybe(false)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}
|
||||
if (!newArray->Set(destFunctionContext, length, v8ThisObject.get()).FromMaybe(false)) {
|
||||
//if (!newArray->Set(destFunctionContext, length, v8ThisObject.get()).FromMaybe(false)) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
if (!destFunction->Set(destFunctionContext, destDataName, newArray).FromMaybe(false)) {
|
||||
|
@ -1448,8 +1469,16 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) {
|
|||
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;
|
||||
auto destFunctionContext = destFunction->CreationContext();
|
||||
|
||||
//auto destFunctionContext = destFunction->CreationContext();
|
||||
auto destFunctionContext = _engine->getContext();
|
||||
Q_ASSERT(thisObject().isObject());
|
||||
V8ScriptValue v8ThisObject = ScriptValueV8Wrapper::fullUnwrap(_engine, thisObject());
|
||||
Q_ASSERT(ScriptObjectV8Proxy::unwrapProxy(v8ThisObject));
|
||||
// For debugging
|
||||
ScriptSignalV8Proxy* thisProxy = dynamic_cast<ScriptSignalV8Proxy*>(ScriptObjectV8Proxy::unwrapProxy(v8ThisObject)->toQObject());
|
||||
Q_ASSERT(thisProxy);
|
||||
qDebug(scriptengine) << "ScriptSignalV8Proxy::disconnect: " << thisProxy->fullName() << " fullName: " << fullName();
|
||||
//V8ScriptValue destData = callback.data();
|
||||
//Q_ASSERT(destData->IsArray());
|
||||
if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) {
|
||||
|
@ -1463,8 +1492,22 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) {
|
|||
int newIndex = 0;
|
||||
for (int idx = 0; idx < length && !foundIt; ++idx) {
|
||||
v8::Local<v8::Value> entry = destArray->Get(destFunctionContext, idx).ToLocalChecked();
|
||||
// For debugging:
|
||||
{
|
||||
_engine->logBacktrace("ScriptSignalV8Proxy::disconnect");
|
||||
qDebug() << "ScriptSignalV8Proxy::disconnect: entry details: " << _engine->scriptValueDebugDetailsV8(V8ScriptValue(_engine, entry));
|
||||
Q_ASSERT(entry->IsObject());
|
||||
V8ScriptValue v8EntryObject(_engine, entry);
|
||||
Q_ASSERT(ScriptObjectV8Proxy::unwrapProxy(v8EntryObject));
|
||||
// For debugging
|
||||
ScriptSignalV8Proxy* entryProxy = dynamic_cast<ScriptSignalV8Proxy*>(ScriptObjectV8Proxy::unwrapProxy(v8EntryObject)->toQObject());
|
||||
Q_ASSERT(thisProxy);
|
||||
qDebug(scriptengine) << "ScriptSignalV8Proxy::disconnect: entry proxy: " << entryProxy->fullName();
|
||||
}
|
||||
if (entry->StrictEquals(v8ThisObject.get())) {
|
||||
//V8TODO: compare proxies instead?
|
||||
foundIt = true;
|
||||
qDebug() << "ScriptSignalV8Proxy::disconnect foundIt";
|
||||
//V8ScriptValueList args;
|
||||
//args << idx << 1;
|
||||
//destData.property("splice").call(destData, args);
|
||||
|
|
|
@ -235,12 +235,14 @@ private: // implementation
|
|||
virtual int qt_metacall(QMetaObject::Call call, int id, void** arguments) override;
|
||||
int discoverMetaCallIdx();
|
||||
ConnectionList::iterator findConnection(V8ScriptValue thisObject, V8ScriptValue callback);
|
||||
QString fullName() const;
|
||||
//QString fullName() const;
|
||||
|
||||
public: // API
|
||||
// arg1 was had Null default value, but that needs isolate pointer to create Null in V8
|
||||
virtual void connect(ScriptValue arg0, ScriptValue arg1 = ScriptValue()) override;
|
||||
virtual void disconnect(ScriptValue arg0, ScriptValue arg1 = ScriptValue()) override;
|
||||
//Moved to public temporarily for debugging:
|
||||
QString fullName() const;
|
||||
|
||||
//virtual void connect(V8ScriptValue arg0) override;
|
||||
//virtual void disconnect(V8ScriptValue arg0) override;
|
||||
|
|
|
@ -162,6 +162,7 @@ namespace REPLACE_ME_WITH_UNIQUE_NAME {
|
|||
* settings = null; // optional best pratice; allows the object to be reclaimed ASAP by the JS garbage collector
|
||||
*/
|
||||
ScriptValue getScopedSettings(const QString& scope) {
|
||||
Q_ASSERT(engine);
|
||||
auto engine = Scriptable::engine();
|
||||
if (!engine) {
|
||||
return ScriptValue();
|
||||
|
|
Loading…
Reference in a new issue