diff --git a/libraries/script-engine/src/ScriptManagerScriptingInterface.cpp b/libraries/script-engine/src/ScriptManagerScriptingInterface.cpp index 8c2d2799f3d..36da99b751a 100644 --- a/libraries/script-engine/src/ScriptManagerScriptingInterface.cpp +++ b/libraries/script-engine/src/ScriptManagerScriptingInterface.cpp @@ -125,3 +125,11 @@ void ScriptManagerScriptingInterface::removeServerEntityScriptMessagesRequest(co _manager->engine()->raiseException("Uuid must not be specified when removeServerEntityScriptMessagesRequest is invoked from entity script"); } } + +QString ScriptManagerScriptingInterface::btoa(const QByteArray &binary) { + return binary.toBase64(); +} + +QByteArray ScriptManagerScriptingInterface::atob(const QString &base64) { + return QByteArray::fromBase64(base64.toUtf8()); +} diff --git a/libraries/script-engine/src/ScriptManagerScriptingInterface.h b/libraries/script-engine/src/ScriptManagerScriptingInterface.h index c1d6bad360d..d319cd30ae3 100644 --- a/libraries/script-engine/src/ScriptManagerScriptingInterface.h +++ b/libraries/script-engine/src/ScriptManagerScriptingInterface.h @@ -581,6 +581,22 @@ class ScriptManagerScriptingInterface : public QObject { Q_INVOKABLE void removeServerEntityScriptMessagesRequest(); Q_INVOKABLE void removeServerEntityScriptMessagesRequest(const QUuid& entityID); + /*@jsdoc + * This decodes Base64 string and returns contents as ArrayBuffer. + * @function Script.atob + * @param {String} base64 - String with Base64-encoded binary data. + * @returns {ArrayBuffer} Decoded binary data. + */ + Q_INVOKABLE QByteArray atob(const QString &base64); + + /*@jsdoc + * This encodes ArrayBuffer and returns Base64-encoded string. + * @function Script.btoa + * @param {ArrayBuffer} binary - Data to be encoded. + * @returns {String} String with Base64-encoded binary data. + */ + Q_INVOKABLE QString btoa(const QByteArray &binary); + signals: /*@jsdoc diff --git a/libraries/script-engine/src/ScriptValueUtils.cpp b/libraries/script-engine/src/ScriptValueUtils.cpp index 5bada98f15b..ea0c40bfc40 100644 --- a/libraries/script-engine/src/ScriptValueUtils.cpp +++ b/libraries/script-engine/src/ScriptValueUtils.cpp @@ -79,6 +79,7 @@ void registerMetaTypes(ScriptEngine* engine) { scriptRegisterMetaType(engine); scriptRegisterMetaType(engine); scriptRegisterMetaType(engine, "QTimer*"); + scriptRegisterMetaType(engine, "QByteArray"); scriptRegisterMetaType(engine); scriptRegisterMetaType(engine); diff --git a/libraries/script-engine/src/v8/FastScriptValueUtils.cpp b/libraries/script-engine/src/v8/FastScriptValueUtils.cpp index 4a6d8728013..d1545e60cba 100644 --- a/libraries/script-engine/src/v8/FastScriptValueUtils.cpp +++ b/libraries/script-engine/src/v8/FastScriptValueUtils.cpp @@ -19,6 +19,48 @@ #ifdef CONVERSIONS_OPTIMIZED_FOR_V8 +ScriptValue qBytearrayToScriptValue(ScriptEngine* engine, const QByteArray &qByteArray) { + auto engineV8 = dynamic_cast(engine); + Q_ASSERT(engineV8); + auto isolate = engineV8->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); + auto context = engineV8->getContext(); + v8::Context::Scope contextScope(context); + v8::Local arrayBuffer = v8::ArrayBuffer::New(isolate, qByteArray.size()); + memcpy(arrayBuffer->GetBackingStore()->Data(), qByteArray.data(), qByteArray.size()); + v8::Local arrayBufferValue = v8::Local::Cast(arrayBuffer); + + return {new ScriptValueV8Wrapper(engineV8, V8ScriptValue(engineV8, arrayBufferValue))}; +} + +bool qBytearrayFromScriptValue(const ScriptValue& object, QByteArray &qByteArray) { + ScriptValueV8Wrapper *proxy = ScriptValueV8Wrapper::unwrap(object); + if (!proxy) { + return false; + } + + auto engineV8 = proxy->getV8Engine(); + + auto isolate = engineV8->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); + auto context = engineV8->getContext(); + v8::Context::Scope contextScope(context); + V8ScriptValue v8ScriptValue = proxy->toV8Value(); + + v8::Local v8Value = v8ScriptValue.get(); + if(!v8Value->IsArrayBuffer()) { + return false; + } + v8::Local arrayBuffer = v8::Local::Cast(v8Value); + qByteArray.resize(arrayBuffer->ByteLength()); + memcpy(qByteArray.data(), arrayBuffer->Data(), arrayBuffer->ByteLength()); + return true; +} + ScriptValue vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) { ScriptValue value = engine->newObject(); @@ -98,6 +140,9 @@ ScriptValue vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) { bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) { ScriptValueV8Wrapper *proxy = ScriptValueV8Wrapper::unwrap(object); + if (!proxy) { + return false; + } auto engineV8 = proxy->getV8Engine(); diff --git a/libraries/script-engine/src/v8/FastScriptValueUtils.h b/libraries/script-engine/src/v8/FastScriptValueUtils.h index 80d97023a54..00deb04d9c1 100644 --- a/libraries/script-engine/src/v8/FastScriptValueUtils.h +++ b/libraries/script-engine/src/v8/FastScriptValueUtils.h @@ -24,6 +24,10 @@ #define CONVERSIONS_OPTIMIZED_FOR_V8 #ifdef CONVERSIONS_OPTIMIZED_FOR_V8 +ScriptValue qBytearrayToScriptValue(ScriptEngine* engine, const QByteArray &qByteArray); + +bool qBytearrayFromScriptValue(const ScriptValue& object, QByteArray &qByteArray); + ScriptValue vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3); bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3);