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

Commit

Permalink
fix(XHR): Don't send sync XHR through ZONE
Browse files Browse the repository at this point in the history
fixes #377
  • Loading branch information
hmdhk authored and mhevery committed Sep 1, 2016
1 parent dcaeddb commit 6e2f13c
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 13 deletions.
36 changes: 23 additions & 13 deletions lib/browser/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ registerElementPatch(_global);
patchXHR(_global);

const XHR_TASK = zoneSymbol('xhrTask');
const XHR_SYNC = zoneSymbol('xhrSync');

interface XHROptions extends TaskData {
target: any;
Expand All @@ -65,7 +66,7 @@ function patchXHR(window: any) {
if (!storedTask) {
data.target[XHR_TASK] = task;
}
setNative.apply(data.target, data.args);
sendNative.apply(data.target, data.args);
return task;
}

Expand All @@ -77,23 +78,32 @@ function patchXHR(window: any) {
// Note - ideally, we would call data.target.removeEventListener here, but it's too late
// to prevent it from firing. So instead, we store info for the event listener.
data.aborted = true;
return clearNative.apply(data.target, data.args);
return abortNative.apply(data.target, data.args);
}

var setNative = patchMethod(window.XMLHttpRequest.prototype, 'send', () => function(self: any, args: any[]) {
var zone = Zone.current;
var openNative = patchMethod(window.XMLHttpRequest.prototype, 'open', () => function(self: any, args: any[]) {
self[XHR_SYNC] = args[2] == false;
return openNative.apply(self, args);
};

This comment has been minimized.

Copy link
@juliemr

juliemr Sep 1, 2016

Member

Missing ) here


var options: XHROptions = {
target: self,
isPeriodic: false,
delay: null,
args: args,
aborted: false
};
return zone.scheduleMacroTask('XMLHttpRequest.send', placeholderCallback, options, scheduleTask, clearTask);
var sendNative = patchMethod(window.XMLHttpRequest.prototype, 'send', () => function(self: any, args: any[]) {
var zone = Zone.current;
if (self[XHR_SYNC]) {
// if the XHR is sync there is no task to schedule, just execute the code.
return sendNative.apply(self, args);
} else {
var options: XHROptions = {
target: self,
isPeriodic: false,
delay: null,
args: args,
aborted: false
};
return zone.scheduleMacroTask('XMLHttpRequest.send', placeholderCallback, options, scheduleTask, clearTask);
}
});

var clearNative = patchMethod(window.XMLHttpRequest.prototype, 'abort', (delegate: Function) => function(self: any, args: any[]) {
var abortNative = patchMethod(window.XMLHttpRequest.prototype, 'abort', (delegate: Function) => function(self: any, args: any[]) {
var task: Task = findPendingTask(self);
if (task && typeof task.type == 'string') {
// If the XHR has already completed, do nothing.
Expand Down
17 changes: 17 additions & 0 deletions test/browser/XMLHttpRequest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,23 @@ describe('XMLHttpRequest', function () {
}
});

it('should work with synchronous XMLHttpRequest', function () {
const log = [];
Zone.current.fork({
name: 'sync-xhr-test',
onHasTask: function(delegate: ZoneDelegate, current: Zone, target: Zone,
hasTaskState: HasTaskState) {
log.push(hasTaskState);
delegate.hasTask(target, hasTaskState);
}
}).run(() => {
var req = new XMLHttpRequest();
req.open('get', '/', false);
req.send();
});
expect(log).toEqual([]);
});

it('should preserve static constants', function() {
expect(XMLHttpRequest.UNSENT).toEqual(0);
expect(XMLHttpRequest.OPENED).toEqual(1);
Expand Down

0 comments on commit 6e2f13c

Please sign in to comment.