diff options
author | bptato <nincsnevem662@gmail.com> | 2024-02-05 15:32:05 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-02-07 22:21:48 +0100 |
commit | 407b525332106d84f18d74f6b51ae2f7a1ed3475 (patch) | |
tree | c4ca2ad55df079b9c49d9361bc3c495a7a5977d0 /src/loader/loaderhandle.nim | |
parent | 168bd542d989c76ce3ff09a29b8d77af448c3c12 (diff) | |
download | chawan-407b525332106d84f18d74f6b51ae2f7a1ed3475.tar.gz |
Incremental rendering
Yay! Admittedly, it is not very useful in its current form, except maybe on very slow networks. The problem is that renderDocument is *slow*, so we only run it when onload fails to consume all bytes from the network in a single pass. Even then, we are guaranteed to get a FOUC, since CSS is only downloaded in finishLoad(). Well, I think it's cool, anyway.
Diffstat (limited to 'src/loader/loaderhandle.nim')
-rw-r--r-- | src/loader/loaderhandle.nim | 110 |
1 files changed, 85 insertions, 25 deletions
diff --git a/src/loader/loaderhandle.nim b/src/loader/loaderhandle.nim index 7a9b3434..5d2dee4e 100644 --- a/src/loader/loaderhandle.nim +++ b/src/loader/loaderhandle.nim @@ -1,3 +1,4 @@ +import std/deques import std/net import std/streams @@ -7,28 +8,72 @@ import io/serialize import io/socketstream import loader/headers -type LoaderHandle* = ref object - ostream: Stream - # Stream for taking input - istream*: PosixStream - # Only the first handle can be redirected, because a) mailcap can only - # redirect the first handle and b) async redirects would result in race - # conditions that would be difficult to untangle. - canredir: bool - sostream: Stream # saved ostream when redirected - sostream_suspend: Stream # saved ostream when suspended - fd: int +import types/url +type + LoaderBufferPage = array[4056, uint8] # 4096 - 8 - 32 + + LoaderBufferObj = object + page*: LoaderBufferPage + len: int + + LoaderBuffer* = ptr LoaderBufferObj + + LoaderHandle* = ref object + ostream*: PosixStream #TODO un-extern + # Stream for taking input + istream*: PosixStream + # Only the first handle can be redirected, because a) mailcap can only + # redirect the first handle and b) async redirects would result in race + # conditions that would be difficult to untangle. + canredir: bool + sostream: Stream # saved ostream when redirected + sostream_suspend: Stream # saved ostream when suspended + fd*: int # ostream fd + currentBuffer*: LoaderBuffer + currentBufferIdx*: int + buffers: Deque[LoaderBuffer] + url*: URL #TODO TODO TODO debug # Create a new loader handle, with the output stream ostream. -proc newLoaderHandle*(ostream: Stream, canredir: bool): LoaderHandle = +proc newLoaderHandle*(ostream: PosixStream, canredir: bool, url: URL): LoaderHandle = return LoaderHandle( ostream: ostream, canredir: canredir, - fd: int(SocketStream(ostream).source.getFd()) + fd: int(SocketStream(ostream).source.getFd()), + url: url ) -proc getFd*(handle: LoaderHandle): int = - return handle.fd +func `[]`*(buffer: LoaderBuffer, i: int): var uint8 {.inline.} = + return buffer[].page[i] + +func cap*(buffer: LoaderBuffer): int {.inline.} = + return buffer[].page.len + +func len*(buffer: LoaderBuffer): var int {.inline.} = + return buffer[].len + +proc `len=`*(buffer: LoaderBuffer, i: int) {.inline.} = + buffer[].len = i + +proc newLoaderBuffer*(): LoaderBuffer = + let buffer = cast[LoaderBuffer](alloc(sizeof(LoaderBufferObj))) + buffer.len = 0 + return buffer + +proc addBuffer*(handle: LoaderHandle, buffer: LoaderBuffer) = + if handle.currentBuffer == nil: + handle.currentBuffer = buffer + else: + handle.buffers.addLast(buffer) + +proc bufferCleared*(handle: LoaderHandle) = + assert handle.currentBuffer != nil + handle.currentBufferIdx = 0 + dealloc(handle.currentBuffer) + if handle.buffers.len > 0: + handle.currentBuffer = handle.buffers.popFirst() + else: + handle.currentBuffer = nil proc addOutputStream*(handle: LoaderHandle, stream: Stream) = if likely(handle.sostream_suspend != nil): @@ -43,8 +88,18 @@ proc addOutputStream*(handle: LoaderHandle, stream: Stream) = # sostream_suspend is never nil when the function is called. # (Feel free to remove this assertion if this changes.) doAssert false - let ms = newMultiStream(handle.ostream, stream) - handle.ostream = ms + #TODO TODO TODO fix this + #let ms = newMultiStream(handle.ostream, stream) + #handle.ostream = ms + +proc setBlocking*(handle: LoaderHandle, blocking: bool) = + #TODO this is stupid + if handle.sostream_suspend != nil and handle.sostream_suspend of SocketStream: + SocketStream(handle.sostream_suspend).setBlocking(blocking) + elif handle.sostream != nil and handle.sostream of SocketStream: + SocketStream(handle.sostream).setBlocking(blocking) + else: + SocketStream(handle.ostream).setBlocking(blocking) proc sendResult*(handle: LoaderHandle, res: int, msg = "") = handle.ostream.swrite(res) @@ -67,23 +122,25 @@ proc sendHeaders*(handle: LoaderHandle, headers: Headers) = let stream = newPosixStream(fd) handle.ostream = stream -proc sendData*(handle: LoaderHandle, p: pointer, nmemb: int) = - handle.ostream.writeData(p, nmemb) - -proc sendData*(handle: LoaderHandle, s: string) = - if s.len > 0: - handle.sendData(unsafeAddr s[0], s.len) +proc sendData*(handle: LoaderHandle, p: pointer, nmemb: int): int = + return handle.ostream.sendData(p, nmemb) proc suspend*(handle: LoaderHandle) = + #TODO TODO TODO fix suspend + doAssert false handle.sostream_suspend = handle.ostream - handle.ostream = newStringStream() + #handle.ostream = newStringStream() proc resume*(handle: LoaderHandle) = + #TODO TODO TODO fix resume + doAssert false + #[ let ss = handle.ostream handle.ostream = handle.sostream_suspend handle.sostream_suspend = nil handle.sendData(ss.readAll()) ss.close() + ]# proc close*(handle: LoaderHandle) = if handle.sostream != nil: @@ -93,6 +150,9 @@ proc close*(handle: LoaderHandle) = # ignore error, that just means the buffer has already closed the stream discard handle.sostream.close() - handle.ostream.close() + if handle.ostream != nil: + handle.ostream.close() + handle.ostream = nil if handle.istream != nil: handle.istream.close() + handle.istream = nil |