Skip to content

haxe.io.Bytes.getData(): BytesData != ArrayBuffer #173

@derRaab

Description

@derRaab

Hi! I'm not sure if that is even an issue, but it took me a while to understand the difference between the Browser based implementation and the one used by node (electron). So I figured others might run into this very specific case as well:

In a nutshell this is the actual runtime difference: Bytes.getData() returns ArrayBuffer in the browser but Buffer in node (electron):

// Browser:
haxe.io.Bytes.getData() : js.lib.ArrayBuffer
// Node (electron):
haxe.io.Bytes.getData() : js.node.Buffer

If you're interested - first the JavaScript runtime error I ran into:

Uncaught (in promise) TypeError: Failed to execute 'decodeAudioData' on 'BaseAudioContext': parameter 1 is not of type 'ArrayBuffer'.
    at AudioContextWaveformVc._onArrayBuffer (AudioContextWaveformVc.hx:126)

This is my little handler causing problems where _audioContext is an AudioContext instance:

function _onArrayBuffer( arrayBuffer : ArrayBuffer ) {
    _audioContext.decodeAudioData( arrayBuffer, _onDecodeAudioSuccess, _onDecodeAudioError );
}

This is my bytes receiving handler, which extracts the needed ArrayBuffer and forwards it:

function _onBytes( data : Bytes ): Void {
    var arrayBuffer : ArrayBuffer = data.getData();
    _onArrayBuffer( arrayBuffer );
}

So if I use Google Chrome and Http to load the bytes it works fine:

var http : Http = new Http( url );
    http.onBytes = _onBytes;
    http.request( true );

BUT if I use the File API to read the bytes, decoding audio throws the TypeError:

var bytes : Bytes = File.getBytes( path );
_onBytes( bytes );

After some research I figured out, that running node (electron), Bytes.getData() actually returns a js.node.Buffer instance:
Bildschirmfoto 2020-09-04 um 12 44 23

So in my case I had to convert the node buffer into an array buffer, which led me to this quite old stack overflow answer:
https://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer/31394257#31394257

Just in case you need that:

class BufferUtil {
    public static function toArrayBuffer(buf:Buffer): ArrayBuffer {
        var ab = new ArrayBuffer(buf.length);
        var view = new Uint8Array(ab);
        for (i in 0...buf.length) {
            view[i] = buf[i];
        }
        return ab;
    }
}

So is Bytes.getData() not consistent on all platforms?
Is this expected behaviour?
Or is this just a very rare edge case?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions