diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2018-07-06 11:20:35 -0400 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2018-07-06 12:22:11 -0400 |
commit | fe404dfce901356dc7a5d38ba70029c72a946f27 (patch) | |
tree | b8ed0d3417e920da1fd4e6278046184d8205a237 /js/fetch.ts | |
parent | 21e1425656ccebb8d31da95acd83991fb7d728fd (diff) |
Import ts file from prototype without change
From commit 559453cf6cc88283bcf8fdeccd387458f5c63165
Excluding v8worker.d.ts, main.ts, and deno.d.ts.
Updates tslint.json to be original settings.
Diffstat (limited to 'js/fetch.ts')
-rw-r--r-- | js/fetch.ts | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/js/fetch.ts b/js/fetch.ts new file mode 100644 index 000000000..c59d41bf5 --- /dev/null +++ b/js/fetch.ts @@ -0,0 +1,146 @@ +// Copyright 2018 Ryan Dahl <ry@tinyclouds.org> +// All rights reserved. MIT License. +import { + assert, + log, + createResolvable, + Resolvable, + typedArrayToArrayBuffer +} from "./util"; +import { pubInternal, sub } from "./dispatch"; +import { deno as pb } from "./msg.pb"; + +export function initFetch() { + sub("fetch", (payload: Uint8Array) => { + const msg = pb.Msg.decode(payload); + assert(msg.command === pb.Msg.Command.FETCH_RES); + const id = msg.fetchResId; + const f = fetchRequests.get(id); + assert(f != null, `Couldn't find FetchRequest id ${id}`); + + f.onMsg(msg); + }); +} + +const fetchRequests = new Map<number, FetchRequest>(); + +class FetchResponse implements Response { + readonly url: string; + body: null; + bodyUsed = false; // TODO + status: number; + statusText = "FIXME"; // TODO + readonly type = "basic"; // TODO + redirected = false; // TODO + headers: null; // TODO + //private bodyChunks: Uint8Array[] = []; + private first = true; + + constructor(readonly req: FetchRequest) { + this.url = req.url; + } + + bodyWaiter: Resolvable<ArrayBuffer>; + arrayBuffer(): Promise<ArrayBuffer> { + this.bodyWaiter = createResolvable(); + return this.bodyWaiter; + } + + blob(): Promise<Blob> { + throw Error("not implemented"); + } + + formData(): Promise<FormData> { + throw Error("not implemented"); + } + + async json(): Promise<object> { + const text = await this.text(); + return JSON.parse(text); + } + + async text(): Promise<string> { + const ab = await this.arrayBuffer(); + const decoder = new TextDecoder("utf-8"); + return decoder.decode(ab); + } + + get ok(): boolean { + return 200 <= this.status && this.status < 300; + } + + clone(): Response { + throw Error("not implemented"); + } + + onHeader: (res: Response) => void; + onError: (error: Error) => void; + + onMsg(msg: pb.Msg) { + if (msg.error !== null && msg.error !== "") { + //throw new Error(msg.error) + this.onError(new Error(msg.error)); + return; + } + + if (this.first) { + this.first = false; + this.status = msg.fetchResStatus; + this.onHeader(this); + } else { + // Body message. Assuming it all comes in one message now. + const ab = typedArrayToArrayBuffer(msg.fetchResBody); + this.bodyWaiter.resolve(ab); + } + } +} + +let nextFetchId = 0; +//TODO implements Request +class FetchRequest { + private readonly id: number; + response: FetchResponse; + constructor(readonly url: string) { + this.id = nextFetchId++; + fetchRequests.set(this.id, this); + this.response = new FetchResponse(this); + } + + onMsg(msg: pb.Msg) { + this.response.onMsg(msg); + } + + destroy() { + fetchRequests.delete(this.id); + } + + start() { + log("dispatch FETCH_REQ", this.id, this.url); + const res = pubInternal("fetch", { + command: pb.Msg.Command.FETCH_REQ, + fetchReqId: this.id, + fetchReqUrl: this.url + }); + assert(res == null); + } +} + +export function fetch( + input?: Request | string, + init?: RequestInit +): Promise<Response> { + const fetchReq = new FetchRequest(input as string); + const response = fetchReq.response; + return new Promise((resolve, reject) => { + // tslint:disable-next-line:no-any + response.onHeader = (response: any) => { + log("onHeader"); + resolve(response); + }; + response.onError = (error: Error) => { + log("onError", error); + reject(error); + }; + fetchReq.start(); + }); +} |