diff options
author | bptato <nincsnevem662@gmail.com> | 2022-12-31 02:14:34 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-12-31 02:14:34 +0100 |
commit | 80b45c0df3f5bbbedb9abfb02fdef608113958e1 (patch) | |
tree | 475cd89df09b4147b8ee6ce9a1ec28954eb6dc30 /src/io | |
parent | 310254b09ee2dd3045648848ca9f60f9f1f7c769 (diff) | |
download | chawan-80b45c0df3f5bbbedb9abfb02fdef608113958e1.tar.gz |
Add promise support to JS
Diffstat (limited to 'src/io')
-rw-r--r-- | src/io/promise.nim | 107 | ||||
-rw-r--r-- | src/io/request.nim | 4 |
2 files changed, 109 insertions, 2 deletions
diff --git a/src/io/promise.nim b/src/io/promise.nim new file mode 100644 index 00000000..46beec6f --- /dev/null +++ b/src/io/promise.nim @@ -0,0 +1,107 @@ +import tables + +type + PromiseState = enum + PROMISE_PENDING, PROMISE_FULFILLED, PROMISE_REJECTED + + EmptyPromise* = ref object of RootObj + cb: (proc()) + next: EmptyPromise + opaque: pointer + state: PromiseState + + Promise*[T] = ref object of EmptyPromise + res: T + get: GetValueProc[T] + + GetValueProc[T] = (proc(opaque: pointer, res: var T)) + + PromiseMap* = object + tab: Table[int, EmptyPromise] + opaque*: pointer + +proc newPromiseMap*(opaque: pointer): PromiseMap = + return PromiseMap( + opaque: opaque + ) + +proc addPromise*[T](map: var PromiseMap, id: int, get: GetValueProc[T]): Promise[T] = + let promise = Promise[T](state: PROMISE_PENDING, get: get, opaque: map.opaque) + map.tab[id] = promise + return promise + +proc addEmptyPromise*(map: var PromiseMap, id: int): EmptyPromise = + let promise = EmptyPromise(state: PROMISE_PENDING, opaque: map.opaque) + map.tab[id] = promise + return promise + +proc resolve*(promise: EmptyPromise) = + var promise = promise + while true: + promise.state = PROMISE_FULFILLED + if promise.cb != nil: + promise.cb() + promise = promise.next + if promise == nil: + break + +proc resolve*[T](promise: Promise[T], res: T) = + if promise.cb != nil: + if promise.get != nil: + promise.get(promise.opaque, promise.res) + promise.get = nil + promise.res = res + promise.resolve() + +proc resolve*(map: var PromiseMap, promiseid: int) = + var promise: EmptyPromise + if map.tab.pop(promiseid, promise): + promise.resolve() + +func empty*(map: PromiseMap): bool = + map.tab.len == 0 + +proc then*(promise: EmptyPromise, cb: (proc())): EmptyPromise {.discardable.} = + if promise == nil: return + promise.cb = cb + promise.next = EmptyPromise() + return promise.next + +proc then*[T](promise: Promise[T], cb: (proc(x: T))): EmptyPromise {.discardable.} = + if promise == nil: return + return promise.then(proc() = + if promise.get != nil: + promise.get(promise.opaque, promise.res) + cb(promise.res)) + +proc then*[T](promise: EmptyPromise, cb: (proc(): Promise[T])): Promise[T] {.discardable.} = + if promise == nil: return + let next = Promise[T]() + promise.then(proc() = + let p2 = cb() + if p2 != nil: + p2.then(proc(x: T) = + next.res = x + next.resolve())) + return next + +proc then*[T](promise: Promise[T], cb: (proc(x: T): EmptyPromise)): EmptyPromise {.discardable.} = + if promise == nil: return + let next = EmptyPromise() + promise.then(proc(x: T) = + let p2 = cb(x) + if p2 != nil: + p2.then(proc() = + 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]() + promise.then(proc(x: T) = + let p2 = cb(x) + if p2 != nil: + p2.then(proc(y: U) = + next.res = y + next.resolve())) + return next diff --git a/src/io/request.nim b/src/io/request.nim index d15696fe..79ba7c0d 100644 --- a/src/io/request.nim +++ b/src/io/request.nim @@ -163,8 +163,8 @@ func newRequest*(url: URL, httpmethod = HTTP_GET, headers = newHeaderList(), destination: destination ) -func newRequest*(url: URL, httpmethod = HTTP_GET, headers: openarray[(string, string)] = [], - body = none(string), multipart = none(MimeData), mode = RequestMode.NO_CORS): Request = +func newRequest*(url: URL, httpmethod = HTTP_GET, headers: seq[(string, string)] = @[], + body = none(string), multipart = none(MimeData), mode = RequestMode.NO_CORS): Request {.jsctor.} = let hl = newHeaderList() for pair in headers: let (k, v) = pair |