diff --git a/test-app/app/src/main/assets/app/tests/byte-buffer-test.js b/test-app/app/src/main/assets/app/tests/byte-buffer-test.js index 64236d881..8ed0e592f 100644 --- a/test-app/app/src/main/assets/app/tests/byte-buffer-test.js +++ b/test-app/app/src/main/assets/app/tests/byte-buffer-test.js @@ -1,5 +1,5 @@ describe("Tests mapped ByteBuffer conversion", function () { - it("should convert ByteBuffer to ArrayBuffer", function () { + it("should convert ByteBuffer to ArrayBuffer [Direct ByteBuffer]", function () { var bb = java.nio.ByteBuffer.allocateDirect(12); var ab = ArrayBuffer.from(bb); var int8arr = new Int8Array(ab); @@ -8,7 +8,16 @@ describe("Tests mapped ByteBuffer conversion", function () { expect(int32arr.length).toBe(3); }); - it("should share the same memory of all typed arrays", function () { + it("should convert ByteBuffer to ArrayBuffer [Indirect ByteBuffer]", function () { + var bb = java.nio.ByteBuffer.allocate(12); + var ab = ArrayBuffer.from(bb); + var int8arr = new Int8Array(ab); + expect(int8arr.length).toBe(12); + var int32arr = new Int32Array(ab); + expect(int32arr.length).toBe(3); + }); + + it("should share the same memory of all typed arrays [Direct ByteBuffer]", function () { var bb = java.nio.ByteBuffer.allocateDirect(12); var ab = ArrayBuffer.from(bb); var int8arr = new Int8Array(ab); @@ -23,13 +32,35 @@ describe("Tests mapped ByteBuffer conversion", function () { expect(value).toBe(0x44332211); }); - it("should keep original ByteBuffer after conversion", function () { + it("should share the same memory of all typed arrays [Indirect ByteBuffer]", function () { + var bb = java.nio.ByteBuffer.allocate(12); + var ab = ArrayBuffer.from(bb); + var int8arr = new Int8Array(ab); + expect(int8arr.length).toBe(12); + var int32arr = new Int32Array(ab); + expect(int32arr.length).toBe(3); + int8arr[0] = 0x11; + int8arr[1] = 0x22; + int8arr[2] = 0x33; + int8arr[3] = 0x44; + var value = int32arr[0]; + expect(value).toBe(0x44332211); + }); + + it("should keep original ByteBuffer after conversion [Direct ByteBuffer]", function () { var bb = java.nio.ByteBuffer.allocateDirect(12); var ab = ArrayBuffer.from(bb); var same = bb === ab.nativeObject; expect(same).toBe(true); }); + it("should keep original ByteBuffer after conversion [Indirect ByteBuffer]", function () { + var bb = java.nio.ByteBuffer.allocate(12); + var ab = ArrayBuffer.from(bb); + var same = bb === ab.nativeObject; + expect(same).toBe(true); + }); + it("should throw exception when ArrayBuffer.from is called with wrong number of arguments", function () { var exceptionCaught = false; try { diff --git a/test-app/runtime/src/main/cpp/ArrayBufferHelper.cpp b/test-app/runtime/src/main/cpp/ArrayBufferHelper.cpp index fd1c614e6..caaeb46db 100644 --- a/test-app/runtime/src/main/cpp/ArrayBufferHelper.cpp +++ b/test-app/runtime/src/main/cpp/ArrayBufferHelper.cpp @@ -8,7 +8,8 @@ using namespace v8; using namespace tns; ArrayBufferHelper::ArrayBufferHelper() - : m_objectManager(nullptr), m_ByteBufferClass(nullptr), m_isDirectMethodID(nullptr) { + : m_objectManager(nullptr), m_ByteBufferClass(nullptr), m_isDirectMethodID(nullptr), + m_remainingMethodID(nullptr), m_getMethodID(nullptr) { } void ArrayBufferHelper::CreateConvertFunctions(Isolate* isolate, const Local& global, ObjectManager* objectManager) { @@ -82,14 +83,34 @@ void ArrayBufferHelper::CreateFromCallbackImpl(const FunctionCallbackInfo auto isDirectBuffer = ret == JNI_TRUE; - if (!isDirectBuffer) { - throw NativeScriptException("Direct ByteBuffer expected)"); - } + Local arrayBuffer; + + if (isDirectBuffer) { + auto data = env.GetDirectBufferAddress(obj); + auto size = env.GetDirectBufferCapacity(obj); + + arrayBuffer = ArrayBuffer::New(isolate, data, size); + } else { + if (m_remainingMethodID == nullptr) { + m_remainingMethodID = env.GetMethodID(m_ByteBufferClass, "remaining", "()I"); + assert(m_remainingMethodID != nullptr); + } + + int bufferRemainingSize = env.CallIntMethod(obj, m_remainingMethodID); - auto data = env.GetDirectBufferAddress(obj); - auto size = env.GetDirectBufferCapacity(obj); + if (m_getMethodID == nullptr) { + m_getMethodID = env.GetMethodID(m_ByteBufferClass, "get", "([BII)Ljava/nio/ByteBuffer;"); + assert(m_getMethodID != nullptr); + } + + jbyteArray byteArray = env.NewByteArray(bufferRemainingSize); + env.CallObjectMethod(obj, m_getMethodID, byteArray, 0, bufferRemainingSize); + + auto buffer = env.GetByteArrayElements(byteArray, 0); + arrayBuffer = ArrayBuffer::New(isolate, bufferRemainingSize); + memcpy(arrayBuffer->GetContents().Data(), buffer, bufferRemainingSize); + } - auto arrayBuffer = ArrayBuffer::New(isolate, data, size); auto ctx = isolate->GetCurrentContext(); arrayBuffer->Set(ctx, ArgConverter::ConvertToV8String(isolate, "nativeObject"), argObj); diff --git a/test-app/runtime/src/main/cpp/ArrayBufferHelper.h b/test-app/runtime/src/main/cpp/ArrayBufferHelper.h index 64737936b..477178bf4 100644 --- a/test-app/runtime/src/main/cpp/ArrayBufferHelper.h +++ b/test-app/runtime/src/main/cpp/ArrayBufferHelper.h @@ -5,24 +5,25 @@ #include "ObjectManager.h" namespace tns { -class ArrayBufferHelper { - public: - ArrayBufferHelper(); + class ArrayBufferHelper { + public: + ArrayBufferHelper(); - void CreateConvertFunctions(v8::Isolate* isolate, const v8::Local& global, ObjectManager* objectManager); + void CreateConvertFunctions(v8::Isolate* isolate, const v8::Local& global, ObjectManager* objectManager); - private: + private: - static void CreateFromCallbackStatic(const v8::FunctionCallbackInfo& info); + static void CreateFromCallbackStatic(const v8::FunctionCallbackInfo& info); - void CreateFromCallbackImpl(const v8::FunctionCallbackInfo& info); + void CreateFromCallbackImpl(const v8::FunctionCallbackInfo& info); - ObjectManager* m_objectManager; + ObjectManager* m_objectManager; - jclass m_ByteBufferClass; - - jmethodID m_isDirectMethodID; -}; + jclass m_ByteBufferClass; + jmethodID m_isDirectMethodID; + jmethodID m_remainingMethodID; + jmethodID m_getMethodID; + }; }