From f46cdc065b371f0361527c46b30320a4572425eb Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Fri, 31 Jul 2020 07:55:43 +0900 Subject: [PATCH] fix(xmlhttprequest): throw exception when invalid state (#123) --- src/xmlhttprequest.ts | 37 +++++++++++++++++++++++++++--- test/integration/xmlhttprequest.ts | 19 ++++++++++++++- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/xmlhttprequest.ts b/src/xmlhttprequest.ts index 7ad47d1..68f6bc0 100644 --- a/src/xmlhttprequest.ts +++ b/src/xmlhttprequest.ts @@ -147,7 +147,11 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget { } // eslint-disable-next-line @typescript-eslint/no-explicit-any - get response(): any { + get response(): ArrayBufferLike | Buffer | string | any | null { + if (this.readyState !== XMLHttpRequest.DONE) { + return null; + } + switch (this.responseType) { case 'arraybuffer': return new Uint8Array(this.#responseBuffer).buffer; @@ -156,14 +160,32 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget { case 'document': return this.responseXML; case 'json': - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(this.responseText); + try { + const text = this.#responseBuffer.toString(); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return JSON.parse(text); + } catch { + return null; + } default: return this.responseText; } } get responseText(): string { + if (this.responseType !== '' && this.responseType !== 'text') { + // TODO: Add human readable message. + throw new DOMException('', 'InvalidStateError'); + } + + if ( + this.readyState !== XMLHttpRequest.LOADING && + this.readyState !== XMLHttpRequest.DONE + ) { + return ''; + } + return this.#responseBuffer.toString(); } @@ -190,6 +212,15 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget { } get responseXML(): null { + if (this.responseType !== '' && this.responseType !== 'document') { + // TODO: Add human readable message. + throw new DOMException('', 'InvalidStateError'); + } + + if (this.readyState !== XMLHttpRequest.DONE) { + return null; + } + return null; } diff --git a/test/integration/xmlhttprequest.ts b/test/integration/xmlhttprequest.ts index c196e1c..fca3154 100644 --- a/test/integration/xmlhttprequest.ts +++ b/test/integration/xmlhttprequest.ts @@ -241,7 +241,7 @@ describe('XMLHttpRequest', () => { }); }); - describe('.responseText', () => { + describe('.response', () => { it('returns object when given JSON', (done) => { const client = new XMLHttpRequest(); @@ -261,6 +261,23 @@ describe('XMLHttpRequest', () => { client.responseType = 'json'; client.send(null); }); + + it('returns null when given invalid JSON', (done) => { + const client = new XMLHttpRequest(); + + client.addEventListener('load', () => { + expect(client.response).toBe(null); + + done(); + }); + + client.open( + 'GET', + `${baseURL}/?body=%7B%22test%22%3A%22value%22&type=application/json` + ); + client.responseType = 'json'; + client.send(null); + }); }); describe('.withCredentials', () => {