Added the vice-versa conversions; you can now translate io.Readers into JS streams.

This commit is contained in:
Tracker-Friendly 2024-10-26 17:05:29 +01:00
parent 18bd0a477a
commit 47970e0051
2 changed files with 105 additions and 6 deletions

55
main.go
View File

@ -39,11 +39,12 @@ func (r *ReadableStream) Read(p []byte) (n int, err error) {
readResult.Call("then", js.FuncOf(func(this js.Value, args []js.Value) interface{} { readResult.Call("then", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
defer waitGroup.Done() defer waitGroup.Done()
if args[0].Get("done").Bool() || args[0].Get("value").Length() == 0 {
err = io.EOF
return nil
}
data := args[0].Get("value") data := args[0].Get("value")
js.CopyBytesToGo(p, data) js.CopyBytesToGo(p, data)
if args[0].Get("done").Bool() {
err = io.EOF
}
n = data.Length() n = data.Length()
return nil return nil
})) }))
@ -162,3 +163,51 @@ func NewWritableStream(stream ...js.Value) *WritableStream {
return &WritableStream{stream: stream} return &WritableStream{stream: stream}
} }
} }
// Now we do the vice versa: Reader to ReadableStream and Writer to WritableStream.
// ReaderToReadableStream converts an io.Reader to a JavaScript ReadableStream.
func ReaderToReadableStream(r io.Reader) js.Value {
return js.Global().Get("ReadableStream").New(map[string]interface{}{
"pull": js.FuncOf(func(this js.Value, args []js.Value) interface{} {
readController := args[0]
return js.Global().Get("Promise").New(js.FuncOf(func(this js.Value, args []js.Value) interface{} {
var buffer []byte
buffer, err := io.ReadAll(r)
if err != nil {
panic(err.Error())
}
if len(buffer) == 0 {
readController.Call("close")
return nil
}
jsBuffer := js.Global().Get("Uint8Array").New(len(buffer))
js.CopyBytesToJS(jsBuffer, buffer)
readController.Call("enqueue", jsBuffer)
readController.Call("close")
args[0].Invoke()
return nil
}))
}),
"type": "bytes",
})
}
// WriterToWritableStream converts an io.Writer to a JavaScript WritableStream.
func WriterToWritableStream(w io.Writer) js.Value {
return js.Global().Get("WritableStream").New(map[string]interface{}{
"write": js.FuncOf(func(this js.Value, args []js.Value) interface{} {
writeBuffer := args[0]
return js.Global().Get("Promise").New(js.FuncOf(func(this js.Value, args []js.Value) interface{} {
buffer := make([]byte, writeBuffer.Length())
js.CopyBytesToGo(buffer, writeBuffer)
_, err := w.Write(buffer)
if err != nil {
panic(err.Error())
}
args[0].Invoke()
return nil
}))
}),
})
}

View File

@ -1,11 +1,9 @@
package main package main
import ( import (
"git.ailur.dev/ailur/jsStreams"
"fmt" "fmt"
"git.ailur.dev/ailur/jsStreams"
"io" "io"
"syscall/js" "syscall/js"
) )
@ -41,5 +39,57 @@ func main() {
return nil return nil
})) }))
js.Global().Set("TryWriterConversions", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go func() {
reader, writer := io.Pipe()
go func() {
writeStream := jsStreams.WriterToWritableStream(writer)
buffer := js.Global().Get("Uint8Array").New(45)
js.CopyBytesToJS(buffer, []byte("Hi, I've been piped through a WritableStream!"))
writeStream.Call("getWriter").Call("write", buffer).Call("then", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go func() {
err := writer.Close()
if err != nil {
fmt.Println(err)
}
}()
return nil
}))
}()
go func() {
fmt.Println("Reading stream...")
m, _ := io.ReadAll(reader)
fmt.Println(string(m))
}()
}()
return nil
}))
js.Global().Set("TryReaderConversions", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go func() {
reader, writer := io.Pipe()
go func() {
_, err := writer.Write([]byte("Hi, I've been piped through a ReadableStream!"))
if err != nil {
fmt.Println(err)
return
}
err = writer.Close()
if err != nil {
fmt.Println(err)
return
}
}()
go func() {
fmt.Println("Reading stream...")
m, _ := io.ReadAll(jsStreams.NewReadableStream(jsStreams.ReaderToReadableStream(reader)))
fmt.Println(string(m))
}()
}()
return nil
}))
select {} select {}
} }