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

Commit

Permalink
fix(xhr): should invoke xhr task after onload is triggered (#1055)
Browse files Browse the repository at this point in the history
  • Loading branch information
JiaLiPassion authored and mhevery committed Jun 18, 2018
1 parent e9536ec commit 2aab9c8
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 9 deletions.
24 changes: 23 additions & 1 deletion lib/browser/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,29 @@ Zone.__load_patch('XHR', (global: any, Zone: ZoneType) => {
// sometimes on some browsers XMLHttpRequest will fire onreadystatechange with
// readyState=4 multiple times, so we need to check task state here
if (!data.aborted && (XMLHttpRequest as any)[XHR_SCHEDULED] && task.state === SCHEDULED) {
task.invoke();
// check whether the xhr has registered onload listener
// if that is the case, the task should invoke after all
// onload listeners finish.
const loadTasks = target['__zone_symbol__loadfalse'];
if (loadTasks && loadTasks.length > 0) {
const oriInvoke = task.invoke;
task.invoke = function() {
// need to load the tasks again, because in other
// load listener, they may remove themselves
const loadTasks = target['__zone_symbol__loadfalse'];
for (let i = 0; i < loadTasks.length; i++) {
if (loadTasks[i] === task) {
loadTasks.splice(i, 1);
}
}
if (!data.aborted && task.state === SCHEDULED) {
oriInvoke.call(task);
}
};
loadTasks.push(task);
} else {
task.invoke();
}
}
}
};
Expand Down
30 changes: 22 additions & 8 deletions test/browser/XMLHttpRequest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,37 @@ describe('XMLHttpRequest', function() {

it('should intercept XHRs and treat them as MacroTasks', function(done) {
let req: XMLHttpRequest;
const testZoneWithWtf =
Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({name: 'TestZone'});
let onStable: any;
const testZoneWithWtf = Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({
name: 'TestZone',
onHasTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, hasTask: HasTaskState) => {
if (!hasTask.macroTask) {
onStable && onStable();
}
}
});

testZoneWithWtf.run(() => {
req = new XMLHttpRequest();
const logs: string[] = [];
req.onload = () => {
// The last entry in the log should be the invocation for the current onload,
// which will vary depending on browser environment. The prior entries
// should be the invocation of the send macrotask.
expect(wtfMock.log[wtfMock.log.length - 3])
.toEqual('> Zone:invokeTask:XMLHttpRequest.send("<root>::ProxyZone::WTF::TestZone")');
logs.push('onload');
};
onStable = function() {
expect(wtfMock.log[wtfMock.log.length - 2])
.toEqual('> Zone:invokeTask:XMLHttpRequest.send("<root>::ProxyZone::WTF::TestZone")');
expect(wtfMock.log[wtfMock.log.length - 1])
.toEqual('< Zone:invokeTask:XMLHttpRequest.send');
if (supportPatchXHROnProperty()) {
expect(wtfMock.log[wtfMock.log.length - 1])
expect(wtfMock.log[wtfMock.log.length - 3])
.toMatch(/\< Zone\:invokeTask.*addEventListener\:load/);
expect(wtfMock.log[wtfMock.log.length - 4])
.toMatch(/\> Zone\:invokeTask.*addEventListener\:load/);
}
// if browser can patch onload
if ((req as any)['__zone_symbol__loadfalse']) {
expect(logs).toEqual(['onload']);
}
done();
};

Expand Down

0 comments on commit 2aab9c8

Please sign in to comment.