diff options
author | bptato <nincsnevem662@gmail.com> | 2023-06-13 01:44:55 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-06-13 01:44:55 +0200 |
commit | eff1e064fde12fd6976919ca76b56c124231b31a (patch) | |
tree | 6df43f3cbbbb340e78b47be6334fe1ef7000e5c5 | |
parent | 3a245434cd4bd75a56700ed7814f78699e3a3dd7 (diff) | |
download | chawan-eff1e064fde12fd6976919ca76b56c124231b31a.tar.gz |
Make Result.text, json return promise
-rw-r--r-- | src/buffer/buffer.nim | 6 | ||||
-rw-r--r-- | src/display/client.nim | 6 | ||||
-rw-r--r-- | src/img/png.nim | 1 | ||||
-rw-r--r-- | src/io/loader.nim | 47 | ||||
-rw-r--r-- | src/io/promise.nim | 12 | ||||
-rw-r--r-- | src/io/request.nim | 19 |
6 files changed, 66 insertions, 25 deletions
diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim index f587c8ee..7a51792a 100644 --- a/src/buffer/buffer.nim +++ b/src/buffer/buffer.nim @@ -1151,8 +1151,7 @@ proc handleRead(buffer: Buffer, fd: int) = elif fd in buffer.loader.connecting: buffer.loader.onConnected(fd) elif fd in buffer.loader.ongoing: - #TODO something with readablestream? - discard + buffer.loader.onRead(fd) elif fd in buffer.loader.unregistered: discard # ignore else: assert false @@ -1167,8 +1166,7 @@ proc handleError(buffer: Buffer, fd: int, err: OSErrorCode) = # probably shouldn't happen. TODO assert false, $fd & ": " & $err elif fd in buffer.loader.ongoing: - #TODO something with readablestream? - discard + buffer.loader.onError(fd) elif fd in buffer.loader.unregistered: discard # ignore else: diff --git a/src/display/client.nim b/src/display/client.nim index d3878e49..9783650f 100644 --- a/src/display/client.nim +++ b/src/display/client.nim @@ -293,8 +293,7 @@ proc handleRead(client: Client, fd: int) = client.loader.onConnected(fd) client.runJSJobs() elif fd in client.loader.ongoing: - #TODO something with readablestream? - discard + client.loader.onRead(fd) elif fd in client.loader.unregistered: discard # ignore else: @@ -317,8 +316,7 @@ proc handleError(client: Client, fd: int) = #TODO handle error? discard elif fd in client.loader.ongoing: - #TODO something with readablestream? - discard + client.loader.onError(fd) elif fd in client.loader.unregistered: discard # already unregistered... else: diff --git a/src/img/png.nim b/src/img/png.nim index 3de395f2..ace31d00 100644 --- a/src/img/png.nim +++ b/src/img/png.nim @@ -413,7 +413,6 @@ proc zlibFree(opaque: pointer, address: pointer) {.cdecl.} = dealloc(address) proc initZStream(reader: var PNGReader) = - let bps = max(int(reader.bitDepth) div 8, 1) reader.idatBuf = newSeq[uint8](reader.scanlen * reader.height) reader.uprow = newSeq[uint8](reader.scanlen) reader.strm = z_stream( diff --git a/src/io/loader.nim b/src/io/loader.nim index 34eb9b42..f40882fc 100644 --- a/src/io/loader.nim +++ b/src/io/loader.nim @@ -23,13 +23,14 @@ import bindings/curl import io/about import io/file import io/http +import io/posixstream import io/promise import io/request import io/urlfilter -import js/javascript import ips/serialize import ips/serversocket import ips/socketstream +import js/javascript import types/cookie import types/mime import types/referer @@ -40,7 +41,7 @@ type FileLoader* = ref object process*: Pid connecting*: Table[int, ConnectData] - ongoing*: Table[int, Response] + ongoing*: Table[int, OngoingData] unregistered*: seq[int] registerFun*: proc(fd: int) unregisterFun*: proc(fd: int) @@ -50,6 +51,11 @@ type stream: Stream request: Request + OngoingData = object + buf: string + readbufsize: int + response: Response + ConnectErrorCode* = enum ERROR_SOURCE_NOT_FOUND = (-4, "clone source could not be found"), ERROR_LOADER_KILLED = (-3, "loader killed during transfer"), @@ -258,9 +264,12 @@ proc newResponse(res: int, request: Request, stream: Stream = nil): Response = return Response( res: res, url: request.url, - body: stream + body: stream, + bodyRead: Promise[string]() ) +const BufferSize = 4096 + proc onConnected*(loader: FileLoader, fd: int) = let connectData = loader.connecting[fd] let stream = connectData.stream @@ -279,7 +288,10 @@ proc onConnected*(loader: FileLoader, fd: int) = stream.sread(response.headers) applyHeaders(request, response) response.body = stream - loader.ongoing[fd] = response + loader.ongoing[fd] = OngoingData( + response: response, + readbufsize: BufferSize, + ) promise.resolve(response) else: loader.unregisterFun(fd) @@ -289,6 +301,33 @@ proc onConnected*(loader: FileLoader, fd: int) = promise.resolve(response) loader.connecting.del(fd) +proc onRead*(loader: FileLoader, fd: int) = + loader.ongoing.withValue(fd, buffer): + let response = buffer[].response + while true: + let olen = buffer[].buf.len + buffer[].buf.setLen(olen + buffer.readbufsize) + try: + let n = response.body.readData(addr buffer[].buf[olen], + buffer.readbufsize) + if n != 0: + if buffer[].readbufsize < BufferSize: + buffer[].readbufsize = min(BufferSize, buffer[].readbufsize * 2) + buffer[].buf.setLen(olen + n) + if response.body.atEnd(): + response.bodyRead.resolve(buffer[].buf) + loader.unregisterFun(fd) + loader.ongoing.del(fd) + loader.unregistered.add(fd) + response.body.close() + break + except ErrorAgain, ErrorWouldBlock: + assert buffer.readbufsize > 1 + buffer.readbufsize = buffer.readbufsize div 2 + +proc onError*(loader: FileLoader, fd: int) = + loader.onRead(fd) + proc doRequest*(loader: FileLoader, request: Request, blocking = true): Response = new(result) result.url = request.url diff --git a/src/io/promise.nim b/src/io/promise.nim index 00702cec..0e1b6115 100644 --- a/src/io/promise.nim +++ b/src/io/promise.nim @@ -1,14 +1,14 @@ import tables type - PromiseState = enum + PromiseState* = enum PROMISE_PENDING, PROMISE_FULFILLED, PROMISE_REJECTED EmptyPromise* = ref object of RootObj cb: (proc()) next: EmptyPromise opaque: pointer - state: PromiseState + state*: PromiseState Promise*[T] = ref object of EmptyPromise res: T @@ -100,6 +100,14 @@ proc then*[T](promise: Promise[T], cb: (proc(x: T): EmptyPromise)): EmptyPromise next.resolve())) return next +proc then*[T, U](promise: Promise[T], cb: (proc(x: T): U)): Promise[U] {.discardable.} = + if promise == nil: return + let next = Promise[U]() + promise.then(proc(x: T) = + next.res = cb(x) + next.resolve()) + return next + proc then*[T, U](promise: Promise[T], cb: (proc(x: T): Promise[U])): Promise[U] {.discardable.} = if promise == nil: return let next = Promise[U]() diff --git a/src/io/request.nim b/src/io/request.nim index 4ae461df..61fee6dd 100644 --- a/src/io/request.nim +++ b/src/io/request.nim @@ -4,9 +4,10 @@ import strutils import tables import bindings/quickjs +import io/promise +import js/javascript import types/formdata import types/url -import js/javascript import utils/twtstr type @@ -84,6 +85,7 @@ type redirect*: Request url*: URL #TODO should be urllist? unregisterFun*: proc() + bodyRead*: Promise[string] ReadableStream* = ref object of Stream isource*: Stream @@ -310,16 +312,13 @@ proc close*(response: Response) {.jsfunc.} = if response.body != nil: response.body.close() -#TODO text, json should return promises, not blocking reads -proc text*(response: Response): string {.jsfunc.} = - if response.body == nil: - return "" - result = response.body.readAll() - response.close() +proc text*(response: Response): Promise[string] {.jsfunc.} = + return response.bodyRead -proc json(response: Response, ctx: JSContext): JSValue {.jsfunc.} = - var s = response.text() - return JS_ParseJSON(ctx, cstring(s), cast[csize_t](s.len), cstring"<input>") +proc json(ctx: JSContext, this: Response): Promise[JSValue] {.jsfunc.} = + return this.text().then(proc(s: string): JSValue = + return JS_ParseJSON(ctx, cstring(s), cast[csize_t](s.len), + cstring"<input>")) func credentialsMode*(attribute: CORSAttribute): CredentialsMode = case attribute |