diff options
Diffstat (limited to 'js/fetch.ts')
-rw-r--r-- | js/fetch.ts | 140 |
1 files changed, 60 insertions, 80 deletions
diff --git a/js/fetch.ts b/js/fetch.ts index 25db32d1d..c0d1dc3e7 100644 --- a/js/fetch.ts +++ b/js/fetch.ts @@ -5,8 +5,7 @@ import { createResolvable, Resolvable, typedArrayToArrayBuffer, - notImplemented, - CreateIterableIterator + notImplemented } from "./util"; import * as flatbuffers from "./flatbuffers"; import { sendAsync } from "./dispatch"; @@ -14,109 +13,90 @@ import * as msg from "gen/msg_generated"; import * as domTypes from "./dom_types"; import { TextDecoder } from "./text_encoding"; import { DenoBlob } from "./blob"; +import { DomIterableMixin } from "./mixins/dom_iterable"; -// ref: https://fetch.spec.whatwg.org/#dom-headers -export class DenoHeaders implements domTypes.Headers { - private headerMap: Map<string, string> = new Map(); +// tslint:disable-next-line:no-any +function isHeaders(value: any): value is domTypes.Headers { + return value instanceof Headers; +} - constructor(init?: domTypes.HeadersInit) { - if (arguments.length === 0 || init === undefined) { - return; - } +const headerMap = Symbol("header map"); - if (init instanceof DenoHeaders) { - // init is the instance of Header - init.forEach((value: string, name: string) => { - this.headerMap.set(name, value); - }); - } else if (Array.isArray(init)) { - // init is a sequence - init.forEach(item => { - if (item.length !== 2) { - throw new TypeError("Failed to construct 'Headers': Invalid value"); - } - const [name, value] = this.normalizeParams(item[0], item[1]); - const v = this.headerMap.get(name); - const str = v ? `${v}, ${value}` : value; - this.headerMap.set(name, str); - }); - } else if (Object.prototype.toString.call(init) === "[object Object]") { - // init is a object - const names = Object.keys(init); - names.forEach(name => { - const value = (init as Record<string, string>)[name]; - const [newname, newvalue] = this.normalizeParams(name, value); - this.headerMap.set(newname, newvalue); - }); - } else { - throw new TypeError("Failed to construct 'Headers': Invalid value"); - } - } +// ref: https://fetch.spec.whatwg.org/#dom-headers +class HeadersBase { + private [headerMap]: Map<string, string>; - private normalizeParams(name: string, value?: string): string[] { + private _normalizeParams(name: string, value?: string): string[] { name = String(name).toLowerCase(); value = String(value).trim(); return [name, value]; } + constructor(init?: domTypes.HeadersInit) { + if (init === null) { + throw new TypeError( + "Failed to construct 'Headers'; The provided value was not valid" + ); + } else if (isHeaders(init)) { + this[headerMap] = new Map(init); + } else { + this[headerMap] = new Map(); + if (Array.isArray(init)) { + for (const [rawName, rawValue] of init) { + const [name, value] = this._normalizeParams(rawName, rawValue); + const existingValue = this[headerMap].get(name); + this[headerMap].set( + name, + existingValue ? `${existingValue}, ${value}` : value + ); + } + } else if (init) { + const names = Object.keys(init); + for (const rawName of names) { + const rawValue = init[rawName]; + const [name, value] = this._normalizeParams(rawName, rawValue); + this[headerMap].set(name, value); + } + } + } + } + append(name: string, value: string): void { - const [newname, newvalue] = this.normalizeParams(name, value); - const v = this.headerMap.get(newname); + const [newname, newvalue] = this._normalizeParams(name, value); + const v = this[headerMap].get(newname); const str = v ? `${v}, ${newvalue}` : newvalue; - this.headerMap.set(newname, str); + this[headerMap].set(newname, str); } delete(name: string): void { - const [newname] = this.normalizeParams(name); - this.headerMap.delete(newname); - } - - entries(): IterableIterator<[string, string]> { - const iterators = this.headerMap.entries(); - return new CreateIterableIterator(iterators); + const [newname] = this._normalizeParams(name); + this[headerMap].delete(newname); } get(name: string): string | null { - const [newname] = this.normalizeParams(name); - const value = this.headerMap.get(newname); + const [newname] = this._normalizeParams(name); + const value = this[headerMap].get(newname); return value || null; } has(name: string): boolean { - const [newname] = this.normalizeParams(name); - return this.headerMap.has(newname); - } - - keys(): IterableIterator<string> { - const iterators = this.headerMap.keys(); - return new CreateIterableIterator(iterators); + const [newname] = this._normalizeParams(name); + return this[headerMap].has(newname); } set(name: string, value: string): void { - const [newname, newvalue] = this.normalizeParams(name, value); - this.headerMap.set(newname, newvalue); - } - - values(): IterableIterator<string> { - const iterators = this.headerMap.values(); - return new CreateIterableIterator(iterators); - } - - forEach( - callbackfn: (value: string, key: string, parent: domTypes.Headers) => void, - // tslint:disable-next-line:no-any - thisArg?: any - ): void { - this.headerMap.forEach((value, name) => { - callbackfn(value, name, this); - }); - } - - [Symbol.iterator](): IterableIterator<[string, string]> { - return this.entries(); + const [newname, newvalue] = this._normalizeParams(name, value); + this[headerMap].set(newname, newvalue); } } +// @internal +// tslint:disable-next-line:variable-name +export const Headers = DomIterableMixin<string, string, typeof HeadersBase>( + HeadersBase, + headerMap +); + class FetchResponse implements domTypes.Response { readonly url: string = ""; body: null; @@ -124,7 +104,7 @@ class FetchResponse implements domTypes.Response { statusText = "FIXME"; // TODO readonly type = "basic"; // TODO redirected = false; // TODO - headers: DenoHeaders; + headers: domTypes.Headers; readonly trailer: Promise<domTypes.Headers>; //private bodyChunks: Uint8Array[] = []; private first = true; @@ -138,7 +118,7 @@ class FetchResponse implements domTypes.Response { ) { this.bodyWaiter = createResolvable(); this.trailer = createResolvable(); - this.headers = new DenoHeaders(headersList); + this.headers = new Headers(headersList); this.bodyData = body_; setTimeout(() => { this.bodyWaiter.resolve(body_); |