How to explicitly call ByteArray.toString(array)?

Following sample code from here, I’m happy to have a so far working app. However it does generate a WARNING the first time the socket callback happens and the received data is expressed as a string. The WARNING message is

(gjs:52764): Gjs-WARNING **: 08:45:51.370: Some code called array.toString() on a Uint8Array instance. Previously this would have interpreted the bytes of the array as a string, but that is nonstandard. In the future this will return the bytes as comma-separated digits. For the time being, the old behavior has been preserved, but please fix your code anyway to explicitly call ByteArray.toString(array).
(Note that array.toString() may have been called implicitly.)
0 anonymous() ["./utest.js":14:74]
1 <TOP LEVEL> ["./utest.js":23:5]

I’m happy to fix your code anyway to explicitly call ByteArray.toString(array) but am unsure how to do that (following a few failed attempts).

Could anyone show me how to make that conversion please?

A short test app which generates this WARNING is:

#!/usr/bin/env gjs
const { GLib, Gio } = imports.gi;

let loop = GLib.MainLoop.new(null, false);

var socket = new Gio.Socket({ "family":Gio.SocketFamily.IPV4, "type":Gio.SocketType.DATAGRAM, "protocol":Gio.SocketProtocol.UDP});
socket.init(null);
socket.bind(Gio.InetSocketAddress.new(Gio.InetAddress.new_any(Gio.SocketFamily.IPV4), 48895), true);
socket.set_blocking(false);
bsock_source = socket.create_source(GLib.IOCondition.IN, Gio.Cancellable.new());
bsock_source_stream = new Gio.UnixInputStream({fd:socket.get_fd(), close_fd:false});
bsock_source.set_callback( () => {
  try {
    log(`Received: ${bsock_source_stream.read_bytes(4096, null).toArray().toString()}`);
    return GLib.SOURCE_CONTINUE;
  } catch (err) {
    log(`XXXXX ${err}`);
    return GLib.SOURCE_REMOVE;
  }
});

bsock_source.attach(null);
loop.run();

Although this test app calls toString() just to enable logging, the real app will also need to use it since the received messages are expected to be JSON strings which I’ll want to convert to JSON objects for processing.

Thanks for any help,
chris

ByteArray.toString() is called — well — exactly like it appears in the message:

const ByteArray = imports.byteArray;

const bytes = bsock_source_stream.read_bytes(4096, null);
log(`Received: ${ByteArray.toString(bytes)`);

Nowadays it is preferred to use the TextDecoder API (since gjs 1.70):

const bytes = bsock_source_stream.read_bytes(4096, null);
const decoder = new TextDecoder();
log(`Received: ${decoder.decode(bytes)`);

Thanks for that Florian,

My mistake with previous attempts was to use GLib.ByteArray.toString(bytes) instead of the imports.ByteArray version. Your version works fine, except I found that bytes declaration needs to be:

const bytes = bsock_source_stream.read_bytes(4096, null).toArray();

(same for the TextDecoder example which I’ll use from now on).

BTW, is there a way to know beforehand that there could exist an “internal” version (not sure if that’s a correct description) of some module rather than a GLib (or Gio, etc.) version? In this case I confused imports.byteArray with GLib.ByteArray but I’m sure there will be more like that to confuse me as I go along.

Thanks again,
chris

Here’s documentation on the built-in modules: https://gitlab.gnome.org/GNOME/gjs/-/blob/master/doc/Modules.md

We should probably change this error message to say TextDecoder, anyway.

1 Like

OK, thanks for that link Philip.

chris

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.