Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.
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
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