uint array behaving differently when using hermes javascript engine

87 views Asked by At

I am creating a mobile (iOS) application that communicates with an esp32 and puts this information on a database (I am using firebase). The esp32 sends an array of bytes to my phone after which I place these bytes in a uint16 array so they can be uploaded to firebase as a blob. The transmission from the esp32 works perfectly and the uploading of the bytes works perfectly when running my script on my computer. But when I try to upload some bytes from my phone I get a file with the actual values as character and not a file with the raw data encoded as binary. I presume that my problem has something to do with hermes treating uint16 arrays as dicts instead of actual arrays because when I log the array instead of getting an actual array in my Xcode terminal I get the following result:

{ '0': 30789, '1': 23107 }

The code I am using to create the array and send the data are the following:

//the base64String is already decoded at an earlier stage
concatTypedArrays(base64String) {
    //Create Uint16Array from data
    const byteArr = new Uint16Array(base64String.length/2);
    for (let i = 0; i < base64String.length; i+=2) {
      const highByte = base64String.charCodeAt(i) << 8;
      const lowByte = base64String.charCodeAt(i + 1);
      byteArr[i / 2] = highByte | lowByte;
    }

    //Append array
    let c = new Uint16Array(this.arr.length + byteArr.length);
    c.set(this.arr, 0);
    c.set(byteArr, this.arr.length);
    this.arr = c

    console.log(this.arr)
}

async function uploadBlob(bytes){
  const newByteRef = doc(collection(db, "PPG"));

  const url = 'PPG/'+newByteRef.id
  const storageRef = ref(storage, url);
  const U8bytes = new Uint8Array(bytes.buffer)
  console.log(U8bytes)

  try{
    await uploadBytes(storageRef, U8bytes)

    const downloadUrl = await getDownloadURL(storageRef)
    console.log(downloadUrl);


    const data = {
      date:Date.now(),
      url:downloadUrl.split("/").slice(-1)[0]
    }

    await setDoc(newByteRef,data)
  } catch (error){
    console.log(error)
  }
}

Output file when ran on my phone: 69,120,67,90 (12 byte file)

Output file when ran on my computer: a binary file (4byte file)

Any suggestions or other ways I can accomplish the same task of creating and uploading a blob to firebase would be appreciated. Thanks in advance

EDIT: I found an even easier way to replicate the error

const base64String = "eEU="
const storageRef = ref(storage, url);
uploadString(storageRef,base64String,'base64')

When running this with node there is no problem but with hermes there is.

1

There are 1 answers

0
SebastiaanTheCoder On

After countless hours of trying different things I finally found the wander in a 2019 GitHub post: https://github.com/firebase/firebase-js-sdk/issues/576#issuecomment-533221157

The problem is apparently with the implementation of Blob in react-native and deleting this class resolves the issue.

import { decode } from 'base-64';

if(typeof atob === 'undefined') {
  global.atob = decode;
}

const Blob = global.Blob;
delete global.Blob;
uploadString(storageRef,base64String,'base64').then((snapshot) => {
  console.log('Uploaded a base64 string!');
  global.Blob = Blob;
});