diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/js/javascript.nim | 7 | ||||
-rw-r--r-- | src/loader/response.nim | 40 | ||||
-rw-r--r-- | src/xhr/xmlhttprequest.nim | 74 |
3 files changed, 112 insertions, 9 deletions
diff --git a/src/js/javascript.nim b/src/js/javascript.nim index 0d49cf86..c744345d 100644 --- a/src/js/javascript.nim +++ b/src/js/javascript.nim @@ -816,7 +816,7 @@ proc addThisName(gen: var JSFuncGenerator, thisname: Option[string]) = func getActualMinArgs(gen: var JSFuncGenerator): int = var ma = gen.minArgs - if gen.thisname.isSome: + if gen.thisname.isSome and not gen.isstatic: dec ma if gen.passCtx: dec ma @@ -1038,9 +1038,10 @@ macro jsfuncn*(jsname: static string, uf: static bool, staticname: static string, fun: typed) = var gen = setupGenerator(fun, FUNCTION, jsname = jsname, unforgeable = uf, isstatic = staticname != "", thisType = staticname) - if gen.minArgs == 0: + if gen.minArgs == 0 and not gen.isstatic: error("Zero-parameter functions are not supported. (Maybe pass Window or Client?)") - gen.addFixParam("this") + if not gen.isstatic: + gen.addFixParam("this") gen.addRequiredParams() gen.addOptionalParams() gen.finishFunCallList() diff --git a/src/loader/response.nim b/src/loader/response.nim index 92aa5c7a..8f7d18b3 100644 --- a/src/loader/response.nim +++ b/src/loader/response.nim @@ -15,7 +15,24 @@ import chakasu/decoderstream import chakasu/encoderstream type + ResponseType* = enum + TYPE_DEFAULT = "default" + TYPE_BASIC = "basic" + TYPE_CORS = "cors" + TYPE_ERROR = "error" + TYPE_OPAQUE = "opaque" + TYPE_OPAQUEREDIRECT = "opaqueredirect" + + #TODO fully implement headers guards + HeadersGuard* = enum + GUARD_IMMUTABLE = "immutable" + GUARD_REQUEST = "request" + GUARD_REQUEST_NO_CORS = "request-no-cors" + GUARD_RESPONSE = "response" + GUARD_NONE = "none" + Response* = ref object + responseType* {.jsget: "type".}: ResponseType res*: int fd*: int body*: Stream @@ -23,6 +40,7 @@ type contentType*: string status* {.jsget.}: uint16 headers* {.jsget.}: Headers + headersGuard: HeadersGuard redirect*: Request url*: URL #TODO should be urllist? unregisterFun*: proc() @@ -41,10 +59,26 @@ proc newResponse*(res: int, request: Request, fd = -1, stream: Stream = nil): fd: fd ) +func makeNetworkError*(): Response = + #TODO use "create" function + #TODO headers immutable + return Response( + res: 0, + responseType: TYPE_ERROR, + status: 0, + headers: newHeaders(), + headersGuard: GUARD_IMMUTABLE + ) + +proc error(): Response {.jsstfunc: "Response".} = + return makeNetworkError() + func sok(response: Response): bool {.jsfget: "ok".} = return response.status in 200u16 .. 299u16 func surl(response: Response): string {.jsfget: "url".} = + if response.responseType == TYPE_ERROR: + return "" return $response.url #TODO: this should be a property of body @@ -56,7 +90,11 @@ proc close*(response: Response) {.jsfunc.} = response.body.close() proc text*(response: Response): Promise[JSResult[string]] {.jsfunc.} = - if response.bodyRead == nil: + if response.body == nil: + let p = newPromise[JSResult[string]]() + p.resolve(JSResult[string].ok("")) + return p + if response.bodyUsed: let p = newPromise[JSResult[string]]() let err = JSResult[string] .err(newTypeError("Body has already been consumed")) diff --git a/src/xhr/xmlhttprequest.nim b/src/xhr/xmlhttprequest.nim index ef0e6601..28fbd50a 100644 --- a/src/xhr/xmlhttprequest.nim +++ b/src/xhr/xmlhttprequest.nim @@ -1,5 +1,13 @@ +import std/options +import std/strutils + import html/event +import js/domexception import js/javascript +import loader/headers +import loader/request +import loader/response +import types/url type XMLHttpRequestResponseType = enum @@ -10,6 +18,16 @@ type TYPE_JSON = "json" TYPE_TEXT = "text" + XMLHttpRequestState = enum + UNSENT = 0u16 + OPENED = 1u16 + HEADERS_RECEIVED = 2u16 + LOADING = 3u16 + DONE = 4u16 + + XMLHttpRequestFlag = enum + SEND_FLAG, UPLOAD_LISTENER_FLAG, SYNC_FLAG + XMLHttpRequestEventTarget = ref object of EventTarget onloadstart {.jsgetset.}: EventHandler onprogress {.jsgetset.}: EventHandler @@ -23,8 +41,14 @@ type XMLHttpRequest = ref object of XMLHttpRequestEventTarget onreadystatechange {.jsgetset.}: EventHandler - readyState {.jsget.}: uint16 + readyState: XMLHttpRequestState upload {.jsget.}: XMLHttpRequestUpload + flags: set[XMLHttpRequestFlag] + requestMethod: HttpMethod + requestURL: URL + authorRequestHeaders: Headers + response: Response + responseType {.jsget.}: XMLHttpRequestResponseType jsDestructor(XMLHttpRequestEventTarget) jsDestructor(XMLHttpRequestUpload) @@ -33,14 +57,54 @@ jsDestructor(XMLHttpRequest) func newXMLHttpRequest(): XMLHttpRequest {.jsctor.} = let upload = XMLHttpRequestUpload() return XMLHttpRequest( - upload: upload + upload: upload, + authorRequestHeaders: newHeaders() ) -proc open(this: XMLHttpRequest, httpMethod, url: string) {.jsfunc.} = - discard #TODO implement +func readyState(this: XMLHttpRequest): uint16 {.jsfget.} = + return uint16(this.readyState) + +proc parseMethod(s: string): DOMResult[HttpMethod] = + return case s.toLowerAscii() + of "get": ok(HTTP_GET) + of "delete": ok(HTTP_DELETE) + of "head": ok(HTTP_HEAD) + of "options": ok(HTTP_OPTIONS) + of "patch": ok(HTTP_PATCH) + of "post": ok(HTTP_POST) + of "put": ok(HTTP_PUT) + of "connect", "trace", "track": + err(newDOMException("Forbidden method", "SecurityError")) + else: + err(newDOMException("Invalid method", "SyntaxError")) + +proc open(this: XMLHttpRequest, httpMethod, url: string): Err[DOMException] + {.jsfunc.} = + let httpMethod = ?parseMethod(httpMethod) + let x = parseURL(url) + if x.isNone: + return err(newDOMException("Invalid URL", "SyntaxError")) + let parsedURL = x.get + #TODO async, username, password arguments + let async = true + #TODO if async is false... probably just throw. + #TODO terminate fetch controller + this.flags.excl(SEND_FLAG) + this.flags.excl(UPLOAD_LISTENER_FLAG) + #TODO set if not async + if async: + this.flags.excl(SYNC_FLAG) + else: + this.flags.incl(SYNC_FLAG) + this.requestMethod = httpMethod + this.authorRequestHeaders = newHeaders() + this.response = makeNetworkError() + this.requestURL = parsedURL + return ok() proc addXMLHttpRequestModule*(ctx: JSContext) = let eventTargetCID = ctx.getClass("EventTarget") let xhretCID = ctx.registerType(XMLHttpRequestEventTarget, eventTargetCID) ctx.registerType(XMLHttpRequestUpload, xhretCID) - ctx.registerType(XMLHttpRequest, xhretCID) + let xhrCID = ctx.registerType(XMLHttpRequest, xhretCID) + ctx.defineConsts(xhrCID, XMLHttpRequestState, uint16) |