diff --git a/src/has.ts b/src/has.ts index 29fedba7..368f61c2 100644 --- a/src/has.ts +++ b/src/has.ts @@ -26,3 +26,26 @@ add('blob', function () { add('node-buffer', 'Buffer' in global && typeof global.Buffer === 'function', true); add('fetch', 'fetch' in global && typeof global.fetch === 'function', true); + +add('web-worker-xhr-upload', new Promise((resolve) => { + if (global.Worker !== undefined && global.URL && global.URL.createObjectURL) { + const blob = new Blob([ `(function () { +self.addEventListener('message', function () { + var xhr = new XMLHttpRequest(); + try { + xhr.upload; + postMessage('true'); + } catch (e) { + postMessage('false'); + } +}); + })()` ], { type: 'application/javascript' }); + const worker = new Worker(URL.createObjectURL(blob)); + worker.addEventListener('message', ({ data: result }) => { + resolve(result === 'true'); + }); + worker.postMessage({}); + } else { + resolve(false); + } +})); diff --git a/src/request/providers/xhr.ts b/src/request/providers/xhr.ts index 4d6245aa..389d8b5c 100644 --- a/src/request/providers/xhr.ts +++ b/src/request/providers/xhr.ts @@ -302,9 +302,11 @@ export default function xhr(url: string, options: XhrRequestOptions = {}): Uploa const uploadObserverPool = new SubscriptionPool(); task.upload = new Observable(observer => uploadObserverPool.add(observer)); - request.upload.addEventListener('progress', event => { - uploadObserverPool.next(event.loaded); - }); + if (has('host-browser') || has('web-worker-xhr-upload')) { + request.upload.addEventListener('progress', event => { + uploadObserverPool.next(event.loaded); + }); + } request.send(options.body || null); diff --git a/tests/unit/request/xhr.ts b/tests/unit/request/xhr.ts index c0172172..ef9eb6ae 100644 --- a/tests/unit/request/xhr.ts +++ b/tests/unit/request/xhr.ts @@ -3,11 +3,10 @@ import * as assert from 'intern/chai!assert'; import * as dojo1xhr from 'dojo/request/xhr'; -import xhrRequest from '../../../src/request/providers/xhr'; +import xhrRequest, { XhrResponse } from '../../../src/request/providers/xhr'; import { Response } from '../../../src/request/interfaces'; import UrlSearchParams from '../../../src/UrlSearchParams'; import has from '@dojo/has/has'; -import { XhrResponse } from '../../../src/request/providers/xhr'; import Promise from '@dojo/shim/Promise'; let echoServerAvailable = false; @@ -553,5 +552,59 @@ registerSuite({ }); } } + }, + + 'Web Workers': { + 'from blob'(this: any) { + const testUrl = location.origin + '/__echo/foo.json'; + const baseUrl = location.origin; + const dfd = this.async(); + + const blob = new Blob([ `(function() { +self.addEventListener('message', function (event) { + testXhr(event.data.baseUrl, event.data.testUrl); +}); + +function testXhr(baseUrl, testUrl) { + importScripts(baseUrl + '/node_modules/@dojo/loader/loader.js'); + + require.config({ + baseUrl: baseUrl, + packages: [ + { name: '@dojo', location: 'node_modules/@dojo' } + ] + }); + + require(['_build/src/request/providers/xhr'], function (xhr) { + xhr.default(testUrl).then(function (response) { + return response.json(); + }).then(function (json) { + self.postMessage({ status: 'success' }); + }).catch(function (e) { + self.postMessage({ status: 'error', message: e.message }); + }); + }); +} + })()` ], { type: 'application/javascript' }); + const worker = new Worker(URL.createObjectURL(blob)); + worker.addEventListener('error', (error) => { + dfd.reject(error.message); + }); + worker.addEventListener('message', ({ data: result }) => { + const { status } = result; + + if (status === 'success') { + dfd.resolve(); + } + else if (status === 'error') { + dfd.reject(result.message); + } + }); + + worker.postMessage({ + baseUrl, + testUrl + }); + } } });