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

Commit 2aab9c8

Browse files
JiaLiPassionmhevery
authored andcommitted
fix(xhr): should invoke xhr task after onload is triggered (#1055)
1 parent e9536ec commit 2aab9c8

2 files changed

Lines changed: 45 additions & 9 deletions

File tree

‎lib/browser/browser.ts‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,29 @@ Zone.__load_patch('XHR', (global: any, Zone: ZoneType) => {
144144
// sometimes on some browsers XMLHttpRequest will fire onreadystatechange with
145145
// readyState=4 multiple times, so we need to check task state here
146146
if(!data.aborted&&(XMLHttpRequestasany)[XHR_SCHEDULED]&&task.state===SCHEDULED){
147-
task.invoke();
147+
// check whether the xhr has registered onload listener
148+
// if that is the case, the task should invoke after all
149+
// onload listeners finish.
150+
constloadTasks=target['__zone_symbol__loadfalse'];
151+
if(loadTasks&&loadTasks.length>0){
152+
constoriInvoke=task.invoke;
153+
task.invoke=function(){
154+
// need to load the tasks again, because in other
155+
// load listener, they may remove themselves
156+
constloadTasks=target['__zone_symbol__loadfalse'];
157+
for(leti=0;i<loadTasks.length;i++){
158+
if(loadTasks[i]===task){
159+
loadTasks.splice(i,1);
160+
}
161+
}
162+
if(!data.aborted&&task.state===SCHEDULED){
163+
oriInvoke.call(task);
164+
}
165+
};
166+
loadTasks.push(task);
167+
}else{
168+
task.invoke();
169+
}
148170
}
149171
}
150172
};

‎test/browser/XMLHttpRequest.spec.ts‎

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,37 @@ describe('XMLHttpRequest', function() {
1717

1818
it('should intercept XHRs and treat them as MacroTasks',function(done){
1919
letreq: XMLHttpRequest;
20-
consttestZoneWithWtf=
21-
Zone.current.fork((Zoneasany)['wtfZoneSpec']).fork({name: 'TestZone'});
20+
letonStable: any;
21+
consttestZoneWithWtf=Zone.current.fork((Zoneasany)['wtfZoneSpec']).fork({
22+
name: 'TestZone',
23+
onHasTask: (delegate: ZoneDelegate,curr: Zone,target: Zone,hasTask: HasTaskState)=>{
24+
if(!hasTask.macroTask){
25+
onStable&&onStable();
26+
}
27+
}
28+
});
2229

2330
testZoneWithWtf.run(()=>{
2431
req=newXMLHttpRequest();
32+
constlogs: string[]=[];
2533
req.onload=()=>{
26-
// The last entry in the log should be the invocation for the current onload,
27-
// which will vary depending on browser environment. The prior entries
28-
// should be the invocation of the send macrotask.
29-
expect(wtfMock.log[wtfMock.log.length-3])
30-
.toEqual('> Zone:invokeTask:XMLHttpRequest.send("<root>::ProxyZone::WTF::TestZone")');
34+
logs.push('onload');
35+
};
36+
onStable=function(){
3137
expect(wtfMock.log[wtfMock.log.length-2])
38+
.toEqual('> Zone:invokeTask:XMLHttpRequest.send("<root>::ProxyZone::WTF::TestZone")');
39+
expect(wtfMock.log[wtfMock.log.length-1])
3240
.toEqual('< Zone:invokeTask:XMLHttpRequest.send');
3341
if(supportPatchXHROnProperty()){
34-
expect(wtfMock.log[wtfMock.log.length-1])
42+
expect(wtfMock.log[wtfMock.log.length-3])
43+
.toMatch(/\<Zone\:invokeTask.*addEventListener\:load/);
44+
expect(wtfMock.log[wtfMock.log.length-4])
3545
.toMatch(/\>Zone\:invokeTask.*addEventListener\:load/);
3646
}
47+
// if browser can patch onload
48+
if((reqasany)['__zone_symbol__loadfalse']){
49+
expect(logs).toEqual(['onload']);
50+
}
3751
done();
3852
};
3953

0 commit comments

Comments
 (0)