summaryrefslogtreecommitdiff
path: root/js/fetch.ts
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2018-07-06 11:20:35 -0400
committerRyan Dahl <ry@tinyclouds.org>2018-07-06 12:22:11 -0400
commitfe404dfce901356dc7a5d38ba70029c72a946f27 (patch)
treeb8ed0d3417e920da1fd4e6278046184d8205a237 /js/fetch.ts
parent21e1425656ccebb8d31da95acd83991fb7d728fd (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.ts146
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();
+ });
+}