read_line_async() reads one line, it’s not called repeatedly for each line. So you need to call it again after processing the previous line (e.g. near the end of the try{} block.
Alternatively, and depending on your needs, you might want to simplify your code not using an async method and call read_line_utf8() repeatedly in a loop. That will depend on what you want to do around the stream reading.
If you’re already using GJS, there’s really no need to use shell scripting. If you are drawing this from the example on gjs.guide, that was really just intended for the purpose of demonstration.
print(stdinStream.read_line_utf8(null));
The return value for Gio.DataInputStream.read_line_utf8() return an array of [String, Number]; the line that was read, and the length of the string. You can deconstruct it if you don’t need the length:
const [line] = stdinStream.read_line_utf8(null);
Your infinite loop is looping, however you are not handling the eventual case of the stream running out of data. It’s returning [null, 0] when there is no more data to be read, and print() is coercing that to a string and printing ,0.