From 7c7ab5a5ab155e7bf4a59c4b8403ad576887c541 Mon Sep 17 00:00:00 2001 From: Markus Sanin Date: Thu, 12 Oct 2023 16:28:06 +0200 Subject: [PATCH 1/5] Split onprogress logic into onloadstart, onprogress & onloadend --- ember-file-upload/src/system/http-request.ts | 25 +++++++++++++++----- ember-file-upload/src/system/upload.ts | 20 ++++++++++++++-- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/ember-file-upload/src/system/http-request.ts b/ember-file-upload/src/system/http-request.ts index 5eb2c89a..1bc5ca59 100644 --- a/ember-file-upload/src/system/http-request.ts +++ b/ember-file-upload/src/system/http-request.ts @@ -29,11 +29,17 @@ function parseResponse(request: XMLHttpRequest): Response { } export default class HTTPRequest { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + onloadstart: (event?: ProgressEvent) => void | undefined; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore onprogress: (event?: ProgressEvent) => void | undefined; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore + onloadend: (event?: ProgressEvent) => void | undefined; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore ontimeout: (event?: ProgressEvent) => void | undefined; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -82,15 +88,22 @@ export default class HTTPRequest { aborted.resolve(); }); - this.request.onloadstart = - this.request.onprogress = - this.request.onloadend = - bind(this, function (evt) { - this.onprogress?.(evt); - }); + this.request.onloadstart = bind(this, function (evt) { + this.onloadstart?.(evt); + }); + + this.request.onprogress = bind(this, function (evt) { + this.onprogress?.(evt); + }); + + this.request.onloadend = bind(this, function (evt) { + this.onloadend?.(evt); + }); if (this.request.upload) { + this.request.upload.onloadstart = this.request.onloadstart; this.request.upload.onprogress = this.request.onprogress; + this.request.upload.onloadend = this.request.onloadend; } this.request.onload = bind(this, function () { diff --git a/ember-file-upload/src/system/upload.ts b/ember-file-upload/src/system/upload.ts index 1d953457..4bc2ecdc 100644 --- a/ember-file-upload/src/system/upload.ts +++ b/ember-file-upload/src/system/upload.ts @@ -87,13 +87,29 @@ export function upload( request.timeout = options.timeout; } - request.onprogress = function (evt) { + request.onloadstart = function (evt) { if (!evt) return; if (!evt.lengthComputable || evt.total === 0) return; file.loaded = evt.loaded; file.size = evt.total; - file.progress = (evt.loaded / evt.total) * 100; + file.progress = (file.loaded / file.size) * 100; + }; + + request.onprogress = function (evt) { + if (!evt) return; + if (!evt.lengthComputable || evt.total === 0) return; + + file.loaded = evt.loaded; + file.progress = (file.loaded / file.size) * 100; + }; + + request.onloadend = function (evt) { + if (!evt) return; + if (!evt.lengthComputable || evt.total === 0) return; + + file.loaded = file.size; + file.progress = (file.loaded / file.size) * 100; }; request.ontimeout = () => { From 6e5bf1ed9534646fc3a02dbb9e529643478b1736 Mon Sep 17 00:00:00 2001 From: Markus Sanin Date: Mon, 23 Oct 2023 07:53:01 +0200 Subject: [PATCH 2/5] Activate progress test --- test-app/tests/integration/progress-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-app/tests/integration/progress-test.ts b/test-app/tests/integration/progress-test.ts index 2450947c..35162c8a 100644 --- a/test-app/tests/integration/progress-test.ts +++ b/test-app/tests/integration/progress-test.ts @@ -26,7 +26,7 @@ class FileTracker { }); } -module.skip('Integration | progress', function (hooks) { +module('Integration | progress', function (hooks) { setupRenderingTest(hooks); setupMirage(hooks); From e4d8cdf802d0053fb79ec1d3fb21c22b424f82db Mon Sep 17 00:00:00 2001 From: Markus Sanin Date: Mon, 23 Oct 2023 07:57:44 +0200 Subject: [PATCH 3/5] resolve merge conflict --- ember-file-upload/src/system/http-request.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ember-file-upload/src/system/http-request.ts b/ember-file-upload/src/system/http-request.ts index ae2c8166..402a02df 100644 --- a/ember-file-upload/src/system/http-request.ts +++ b/ember-file-upload/src/system/http-request.ts @@ -29,11 +29,17 @@ function parseResponse(request: XMLHttpRequest): Response { } export default class HTTPRequest { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + onloadstart: (event?: ProgressEvent) => void | undefined; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore onprogress: (event?: ProgressEvent) => void | undefined; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore + onloadend: (event?: ProgressEvent) => void | undefined; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore ontimeout: (event?: ProgressEvent) => void | undefined; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore From 4a05790058417caa7b9e5497eb8a7794fc814e33 Mon Sep 17 00:00:00 2001 From: Markus Sanin Date: Mon, 23 Oct 2023 08:04:00 +0200 Subject: [PATCH 4/5] Call correct functions in `onloadstart` & `onloadend` --- ember-file-upload/src/system/http-request.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ember-file-upload/src/system/http-request.ts b/ember-file-upload/src/system/http-request.ts index 402a02df..6388d08b 100644 --- a/ember-file-upload/src/system/http-request.ts +++ b/ember-file-upload/src/system/http-request.ts @@ -89,19 +89,19 @@ export default class HTTPRequest { }); this.request.onloadstart = bind(this, function (evt) { - this.onprogress?.(evt); + this.onloadstart?.(evt); }); this.request.onprogress = bind(this, function (evt) { this.onprogress?.(evt); }); this.request.onloadend = bind(this, function (evt) { - this.onprogress?.(evt); + this.onloadend?.(evt); }); if (this.request.upload) { - this.request.upload.onloadstart = this.request.onprogress; + this.request.upload.onloadstart = this.request.onloadstart; this.request.upload.onprogress = this.request.onprogress; - this.request.upload.onloadend = this.request.onprogress; + this.request.upload.onloadend = this.request.onloadend; } this.request.onload = bind(this, function () { From f351038f5ecf051cf5f7879dba36f8e4581fe22b Mon Sep 17 00:00:00 2001 From: Markus Sanin Date: Mon, 23 Oct 2023 08:04:28 +0200 Subject: [PATCH 5/5] Fix lint errors --- ember-file-upload/src/system/http-request.ts | 310 +++++++++---------- 1 file changed, 155 insertions(+), 155 deletions(-) diff --git a/ember-file-upload/src/system/http-request.ts b/ember-file-upload/src/system/http-request.ts index 6388d08b..6279f4a3 100644 --- a/ember-file-upload/src/system/http-request.ts +++ b/ember-file-upload/src/system/http-request.ts @@ -1,155 +1,155 @@ -import { bind } from '@ember/runloop'; -import RSVP from 'rsvp'; -import { HTTPRequestOptions } from '../interfaces.ts'; - -function parseHeaders(headerString: string) { - return headerString - .split(/\n|\r/) - .filter((str) => str !== '') - .reduce((headers: Headers, headerString: string) => { - const parts = headerString.split(/^([0-9A-Za-z_-]*:)/); - if (parts.length > 0 && parts[1] && parts[2]) { - headers.append(parts[1].slice(0, -1), parts[2].trim()); - } - return headers; - }, new Headers()); -} - -function parseResponse(request: XMLHttpRequest): Response { - const body = request.response === '' ? null : request.response; - if (request.status >= 200 && request.status < 600) { - return new Response(body, { - status: request.status, - statusText: request.statusText, - headers: parseHeaders(request.getAllResponseHeaders()), - }); - } else { - return Response.error(); - } -} - -export default class HTTPRequest { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - onloadstart: (event?: ProgressEvent) => void | undefined; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - onprogress: (event?: ProgressEvent) => void | undefined; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - onloadend: (event?: ProgressEvent) => void | undefined; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - ontimeout: (event?: ProgressEvent) => void | undefined; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - onabort: (event?: ProgressEvent) => void | undefined; - - request; - resolve; - reject; - promise: RSVP.Promise; - - constructor(options: HTTPRequestOptions = {}) { - const { resolve, reject, promise } = RSVP.defer( - `ember-file-upload: ${options.label}`, - ); - this.resolve = resolve; - this.reject = reject; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - this.promise = promise; - this.request = new XMLHttpRequest(); - - this.request.withCredentials = options.withCredentials ?? false; - - let aborted: RSVP.Deferred; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - promise.cancel = () => { - if (aborted == null) { - aborted = RSVP.defer(`ember-file-upload: Abort ${options.label}`); - this.request.abort(); - } - return aborted.promise; - }; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - promise.then = function (...args) { - const newPromise = RSVP.Promise.prototype.then.apply(this, args); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - newPromise.cancel = promise.cancel; - newPromise.then = promise.then; - return newPromise; - }; - this.request.onabort = bind(this, function () { - this.onabort?.(); - aborted.resolve(); - }); - - this.request.onloadstart = bind(this, function (evt) { - this.onloadstart?.(evt); - }); - this.request.onprogress = bind(this, function (evt) { - this.onprogress?.(evt); - }); - this.request.onloadend = bind(this, function (evt) { - this.onloadend?.(evt); - }); - - if (this.request.upload) { - this.request.upload.onloadstart = this.request.onloadstart; - this.request.upload.onprogress = this.request.onprogress; - this.request.upload.onloadend = this.request.onloadend; - } - - this.request.onload = bind(this, function () { - const response = parseResponse(this.request); - if (Math.floor(response.status / 200) === 1) { - resolve(response); - } else { - reject(response); - } - }); - - this.request.onerror = bind(this, function () { - reject(parseResponse(this.request)); - }); - - Object.defineProperty(this, 'timeout', { - get() { - return this.request.timeout; - }, - set(timeout) { - this.request.timeout = timeout; - }, - enumerable: true, - configurable: false, - }); - - this.request.ontimeout = bind(this, function () { - this.ontimeout?.(); - reject(parseResponse(this.request)); - }); - } - - send(body: Parameters[0]) { - this.request.send(body); - return this.promise; - } - - open( - method: string, - url: string | URL, - _async: boolean, - usename?: string, - password?: string, - ) { - this.request.open(method, url, true, usename, password); - } - - setRequestHeader(name: string, value: string) { - this.request.setRequestHeader(name, value); - } -} +import { bind } from '@ember/runloop'; +import RSVP from 'rsvp'; +import { HTTPRequestOptions } from '../interfaces.ts'; + +function parseHeaders(headerString: string) { + return headerString + .split(/\n|\r/) + .filter((str) => str !== '') + .reduce((headers: Headers, headerString: string) => { + const parts = headerString.split(/^([0-9A-Za-z_-]*:)/); + if (parts.length > 0 && parts[1] && parts[2]) { + headers.append(parts[1].slice(0, -1), parts[2].trim()); + } + return headers; + }, new Headers()); +} + +function parseResponse(request: XMLHttpRequest): Response { + const body = request.response === '' ? null : request.response; + if (request.status >= 200 && request.status < 600) { + return new Response(body, { + status: request.status, + statusText: request.statusText, + headers: parseHeaders(request.getAllResponseHeaders()), + }); + } else { + return Response.error(); + } +} + +export default class HTTPRequest { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + onloadstart: (event?: ProgressEvent) => void | undefined; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + onprogress: (event?: ProgressEvent) => void | undefined; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + onloadend: (event?: ProgressEvent) => void | undefined; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + ontimeout: (event?: ProgressEvent) => void | undefined; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + onabort: (event?: ProgressEvent) => void | undefined; + + request; + resolve; + reject; + promise: RSVP.Promise; + + constructor(options: HTTPRequestOptions = {}) { + const { resolve, reject, promise } = RSVP.defer( + `ember-file-upload: ${options.label}`, + ); + this.resolve = resolve; + this.reject = reject; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this.promise = promise; + this.request = new XMLHttpRequest(); + + this.request.withCredentials = options.withCredentials ?? false; + + let aborted: RSVP.Deferred; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + promise.cancel = () => { + if (aborted == null) { + aborted = RSVP.defer(`ember-file-upload: Abort ${options.label}`); + this.request.abort(); + } + return aborted.promise; + }; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + promise.then = function (...args) { + const newPromise = RSVP.Promise.prototype.then.apply(this, args); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + newPromise.cancel = promise.cancel; + newPromise.then = promise.then; + return newPromise; + }; + this.request.onabort = bind(this, function () { + this.onabort?.(); + aborted.resolve(); + }); + + this.request.onloadstart = bind(this, function (evt) { + this.onloadstart?.(evt); + }); + this.request.onprogress = bind(this, function (evt) { + this.onprogress?.(evt); + }); + this.request.onloadend = bind(this, function (evt) { + this.onloadend?.(evt); + }); + + if (this.request.upload) { + this.request.upload.onloadstart = this.request.onloadstart; + this.request.upload.onprogress = this.request.onprogress; + this.request.upload.onloadend = this.request.onloadend; + } + + this.request.onload = bind(this, function () { + const response = parseResponse(this.request); + if (Math.floor(response.status / 200) === 1) { + resolve(response); + } else { + reject(response); + } + }); + + this.request.onerror = bind(this, function () { + reject(parseResponse(this.request)); + }); + + Object.defineProperty(this, 'timeout', { + get() { + return this.request.timeout; + }, + set(timeout) { + this.request.timeout = timeout; + }, + enumerable: true, + configurable: false, + }); + + this.request.ontimeout = bind(this, function () { + this.ontimeout?.(); + reject(parseResponse(this.request)); + }); + } + + send(body: Parameters[0]) { + this.request.send(body); + return this.promise; + } + + open( + method: string, + url: string | URL, + _async: boolean, + usename?: string, + password?: string, + ) { + this.request.open(method, url, true, usename, password); + } + + setRequestHeader(name: string, value: string) { + this.request.setRequestHeader(name, value); + } +}