Closed ianopolous closed 8 years ago
There are two issues with what you are trying to do.
First: DoppioJVM does not directly map JVM arrays to JS arrays, since JVM arrays are also JVM objects -- so they have a class, methods, etc. DoppioJVM wraps JS arrays and typed arrays in a JVM object with an array
property, which you need to construct like other JVM objects.
Second: a byte[]
array is an Int8Array
-- they are signed integers. You need to convert the Uint8Array
into an Int8Array
first.
Once you have the Int8Array
, you can do the following to construct a byte array with no copying:
Doppio.VM.Util.newArrayFromDataWithClass(thread, thread.getBsCl().getInitializedClass(thread, '[B'), i8Array);
Also, if you have assertion checking enabled, you are using a development build of DoppioJVM (which is super useful for debugging). Hopefully that is intentional. :)
If it is not, you should use a much faster release build of DoppioJVM that strips assertions from the JVM once you have something shippable.
Excellent, thank you! That fixed it. For the reference of others I had to do:
var hashedBytes = some UInt8Array....;
var i8Array = new Int8Array(hashedBytes);
var javaByteArray = Doppio.VM.Util.newArrayFromDataWithClass(thread, thread.getBsCl().getInitializedClass(thread, '[B'), i8Array);
thread.asyncReturn(javaByteArray);
Note that your solution is actually copying the Uint8Array
.
When called with a typedArray argument, which can be an object of any of the typed array types (such as Int32Array), the typedArray gets copied into a new typed array. Each value in typedArray is converted to the corresponding type of the constructor before being copied into the new array.
To do it zero-copy, you need to pass in the raw ArrayBuffer
, byteOffset
, and byteLength
:
When called with a buffer, and optionally a byteOffset and a length argument, a new typed array view is created that views the specified ArrayBuffer. The byteOffset and length parameters specify the memory range that will be exposed by the typed array view. If both are omitted, all of buffer is viewed; if only length is omitted, the remainder of buffer is viewed.
Example:
var i8Array = new Int8Array(hashedBytes.buffer, hashedBytes.byteOffset, hashedBytes.byteLength);
Thanks, John. In this case it's only 96 bytes, but I'll need that later on for 5MiB arrays after erasure decoding.
I'm returning what I believe is a Uint8Array from a "native" JS method, but it is throwing this exception in AsyncReturn().
assert.ts:8 Uncaught Error: Assertion failed: Invalid array object: 216,129,120,126,226,157,61,141,153,225,159,227,200,40,203,202,249,120,249,143,248,65,209,240,79,45,29,238,15,59,146,112,194,49,135,45,14,166,46,84,12,195,4,170,223,204,115,60,246,226,50,36,148,28,15,128,141,7,169,143,59,116,203,90,218,149,20,27,181,163,27,74,14,223,128,57,64,149,244,252,217,77,73,182,225,165,78,30,144,113,32,215,124,81,210,170
Code is at: https://github.com/ianopolous/Peergos/blob/doppio/ui/doppio/natives/peergos_crypto_hash_ScryptJS.js