Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Fixing queue in a web worker #108

Merged
merged 3 commits into from
Aug 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/support/has.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,11 @@ add('es6-weakmap', () => {

/* Miscellaneous features */
add('microtasks', () => has('es6-promise') || has('host-node') || has('dom-mutationobserver'), true);
add('postmessage', () => typeof global.postMessage === 'function', true);
add('postmessage', () => {
// If window is undefined, and we have postMessage, it probably means we're in a web worker. Web workers have
// post message but it doesn't work how we expect it to, so it's best just to pretend it doesn't exist.
return typeof global.window !== 'undefined' && typeof global.postMessage === 'function';
}, true);
add('raf', () => typeof global.requestAnimationFrame === 'function', true);
add('setimmediate', () => typeof global.setImmediate !== 'undefined', true);

Expand Down
51 changes: 49 additions & 2 deletions tests/unit/support/queue.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as registerSuite from 'intern!object';
import * as assert from 'intern/chai!assert';
import global from '../../../src/global';
import has from '../../../src/support/has';
import { queueTask, queueAnimationTask, queueMicroTask } from '../../../src/support/queue';
import { queueAnimationTask, queueMicroTask, queueTask } from '../../../src/support/queue';

registerSuite({
name: 'queue functions',
Expand Down Expand Up @@ -145,7 +146,7 @@ registerSuite({
// executed. As a result, the following just tests that queueMicroTask executes its
// callbacks before either queueTask or queueAnimationTask.
assert.equal(actual.indexOf('start,end,queueMicroTask'), 0);
}), 300);
}), 1000);
},

'.queueMicroTask() => handle.destroy()': function (this: any) {
Expand All @@ -166,5 +167,51 @@ registerSuite({
setTimeout(dfd.callback(function () {
assert.equal(parts.join(','), 'start,end');
}), 100);
},

'web workers': {
'queue from webworker': function (this: any) {
if (global.Blob === undefined || global.Worker === undefined) {
this.skip('does not support blobs and/or web workers');
return;
}

const baseUrl = location.origin;
const dfd = this.async(10000);
const blob = new Blob([ `(function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Android 4.4.4 supports WebWorkers but doesn't support Blob creation this way. Again, not a big deal, but maybe add a simply blob check too?

Also, this might be a good pattern for doing these tests (thank you!) and might want to consider opening an issue on test-extras to add this as some sort of helper.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up adding a simple global.Blob === undefined instead of a real Blob has check. The real Blob check is in core and has a few dependencies that we'd also have to copy over. Maybe that would be worth while at some point?

self.addEventListener('message', function (event) {
if(event.data.baseUrl) {
var baseUrl = event.data.baseUrl;
importScripts(baseUrl + '/node_modules/@dojo/loader/loader.js');

require.config({
baseUrl: baseUrl,
packages: [
{ name: '@dojo', location: 'node_modules/@dojo' }
]
});

require(['_build/src/support/queue'], function (queue) {
queue.queueTask(function() {
self.postMessage('success');
});
});
}
});
})()` ], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
worker.addEventListener('error', (error) => {
dfd.reject(new Error(error.message));
});
worker.addEventListener('message', ({ data: result }) => {
if (result === 'success') {
dfd.resolve();
}
});

worker.postMessage({
baseUrl
});
}
}
});