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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions