Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
fix(WebWorker): Patch WebSockets and XMLHttpRequest in WebWorker
Browse files Browse the repository at this point in the history
Closes #249
  • Loading branch information
jteplitz committed Feb 17, 2016
1 parent 8400b3f commit 45a6bc1
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 16 deletions.
8 changes: 7 additions & 1 deletion karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ module.exports = function (config) {
basePath: '',
files: [
'test/browser_entry_point.ts',
'test/zone_worker_entry_point.ts',
'test/**/*.spec.ts',
{pattern: 'test/assets/**/*.*', watched: true, served: true, included: false},
// Autowatcch all files to trigger rerun
{pattern: 'lib/**/*.ts', watched: true, served: false, included: false},
{pattern: 'test/**/*.ts', watched: true, served: false, included: false}
{pattern: 'test/**/*.ts', watched: true, served: false, included: false},
{pattern: 'test/ws-webworker-context.ts', watched: true, served: true, included: false},

{pattern: 'dist/**/*.js', watched: true, served: true, included: false}
],

/*
Expand All @@ -23,7 +27,9 @@ module.exports = function (config) {

preprocessors: {
'test/browser_entry_point.ts': [ 'webpack', 'sourcemap' ],
'test/zone_worker_entry_point.ts': [ 'webpack', 'sourcemap' ],
'test/**/*.spec.ts': [ 'webpack', 'sourcemap' ],
'test/ws-webworker-context.ts': ['webpack', 'sourcemap']
},
webpack: {
devtool: 'source-map',
Expand Down
30 changes: 17 additions & 13 deletions lib/patch/property-descriptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,28 @@ import * as keys from '../keys';
var eventNames = 'copy cut paste abort blur focus canplay canplaythrough change click contextmenu dblclick drag dragend dragenter dragleave dragover dragstart drop durationchange emptied ended input invalid keydown keypress keyup load loadeddata loadedmetadata loadstart message mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup pause play playing progress ratechange reset scroll seeked seeking select show stalled submit suspend timeupdate volumechange waiting mozfullscreenchange mozfullscreenerror mozpointerlockchange mozpointerlockerror error webglcontextrestored webglcontextlost webglcontextcreationerror'.split(' ');

export function apply() {
if (utils.isWebWorker()){
// on WebWorker so don't apply patch
if (utils.isNode()) {
return;
}

var supportsWebSocket = typeof WebSocket !== 'undefined';
if (canPatchViaPropertyDescriptor()) {
// for browsers that we can patch the descriptor: Chrome & Firefox
var onEventNames = eventNames.map(function (property) {
return 'on' + property;
});
utils.patchProperties(HTMLElement.prototype, onEventNames);
if (!utils.isWebWorker()){
var onEventNames = eventNames.map(function (property) {
return 'on' + property;
});
utils.patchProperties(HTMLElement.prototype, onEventNames);
}
utils.patchProperties(XMLHttpRequest.prototype);
if (supportsWebSocket) {
utils.patchProperties(WebSocket.prototype);
}
} else {
// Safari, Android browsers (Jelly Bean)
patchViaCapturingAllTheEvents();
if (!utils.isWebWorker()){
patchViaCapturingAllTheEvents();
}
utils.patchClass('XMLHttpRequest');
if (supportsWebSocket) {
webSocketPatch.apply();
Expand All @@ -32,21 +35,22 @@ export function apply() {
}

function canPatchViaPropertyDescriptor() {
if (!Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'onclick') && typeof Element !== 'undefined') {
if (!utils.isWebWorker() && !Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'onclick')
&& typeof Element !== 'undefined') {
// WebKit https://bugs.webkit.org/show_bug.cgi?id=134364
// IDL interface attributes are not configurable
var desc = Object.getOwnPropertyDescriptor(Element.prototype, 'onclick');
if (desc && !desc.configurable) return false;
}

Object.defineProperty(HTMLElement.prototype, 'onclick', {
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', {
get: function () {
return true;
}
});
var elt = document.createElement('div');
var result = !!elt.onclick;
Object.defineProperty(HTMLElement.prototype, 'onclick', {});
var req = new XMLHttpRequest();
var result = !!req.onreadystatechange;
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', {});
return result;
};

Expand Down
2 changes: 1 addition & 1 deletion lib/patch/register-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {_redefineProperty} from './define-property';
import * as utils from '../utils';

export function apply() {
if (utils.isWebWorker() || !('registerElement' in (<any>global).document)) {
if (utils.isWebWorker() || utils.isNode() || !('registerElement' in (<any>global).document)) {
return;
}

Expand Down
8 changes: 7 additions & 1 deletion lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as keys from './keys';
// Hack since TypeScript isn't compiling this for a worker.
declare var WorkerGlobalScope;

export function bindArguments(args) {
for (var i = args.length - 1; i >= 0; i--) {
Expand All @@ -21,7 +23,11 @@ export function patchPrototype(obj, fnNames) {
};

export function isWebWorker() {
return (typeof document === "undefined");
return (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope);
}

export function isNode() {
return (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]');
}

export function patchProperty(obj, prop) {
Expand Down
9 changes: 9 additions & 0 deletions test/patch/WebSocket.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ describe('WebSocket', ifEnvSupports('WebSocket', function () {
});


it('should be patched in a Web Worker', done => {
var worker = new Worker('/base/test/ws-webworker-context.ts');
worker.onmessage = (e:MessageEvent) => {
expect(e.data).toBe('pass');
done();
}
});


it('should work with addEventListener', function (done) {
testZone.run(function() {
socket.addEventListener('message', function (event) {
Expand Down
17 changes: 17 additions & 0 deletions test/ws-webworker-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
declare var zone;
importScripts('/base/test/zone_worker_entry_point.ts');

zone.fork().run(() => {
var websocket = new WebSocket('ws://localhost:8001');
websocket.addEventListener('open', () => {
var outerZone = (<any>self).zone;
websocket.onmessage = () => {
if((<any>self).zone.parent === outerZone) {
(<any>self).postMessage('pass');
} else {
(<any>self).postMessage('fail');
}
};
websocket.send('text');
});
});
2 changes: 2 additions & 0 deletions test/zone_worker_entry_point.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Setup tests for Zone without microtask support
import '../lib/browser/zone';

0 comments on commit 45a6bc1

Please sign in to comment.