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

Commit 14c7a6f

Browse files
JiaLiPassionmhevery
authored andcommitted
fix(task): findEventTask should return Task array (#633)
1 parent c07560f commit 14c7a6f

5 files changed

Lines changed: 76 additions & 16 deletions

File tree

lib/browser/browser.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,16 +146,16 @@ if (_global['navigator'] && _global['navigator'].geolocation) {
146146
// handle unhandled promise rejection
147147
function findPromiseRejectionHandler(evtName: string) {
148148
return function(e: any) {
149-
const eventTask = findEventTask(_global, evtName);
150-
if (eventTask) {
149+
const eventTasks = findEventTask(_global, evtName);
150+
eventTasks.forEach(eventTask => {
151151
// windows has added unhandledrejection event listener
152152
// trigger the event listener
153153
const PromiseRejectionEvent = _global['PromiseRejectionEvent'];
154154
if (PromiseRejectionEvent) {
155155
const evt = new PromiseRejectionEvent(evtName, {promise: e.promise, reason: e.rejection});
156156
eventTask.invoke(evt);
157157
}
158-
}
158+
});
159159
};
160160
}
161161

lib/common/utils.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -554,17 +554,18 @@ export function patchMicroTask(
554554
});
555555
}
556556

557-
export function findEventTask(target: any, evtName: string) {
557+
export function findEventTask(target: any, evtName: string): Task[] {
558558
const eventTasks: Task[] = target[zoneSymbol('eventTasks')];
559+
const result: Task[] = [];
559560
if (eventTasks) {
560561
for (let i = 0; i < eventTasks.length; i++) {
561562
const eventTask = eventTasks[i];
562563
const data = eventTask.data;
563564
const eventName = data && (<any>data).eventName;
564565
if (eventName === evtName) {
565-
return eventTask;
566+
result.push(eventTask);
566567
}
567568
}
568569
}
569-
return undefined;
570+
return result;
570571
}

lib/node/node.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,16 @@ function patchProcess() {
7373
// handle unhandled promise rejection
7474
function findProcessPromiseRejectionHandler(evtName: string) {
7575
return function(e: any) {
76-
const eventTask = findEventTask(process, evtName);
77-
if (eventTask) {
76+
const eventTasks = findEventTask(process, evtName);
77+
eventTasks.forEach(eventTask => {
7878
// process has added unhandledrejection event listener
7979
// trigger the event listener
8080
if (evtName === 'unhandledRejection') {
8181
eventTask.invoke(e.rejection, e.promise);
8282
} else if (evtName === 'rejectionHandled') {
8383
eventTask.invoke(e.promise);
8484
}
85-
}
85+
});
8686
};
8787
}
8888

test/browser/browser.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,34 @@ describe('Zone', function() {
193193
});
194194
});
195195
});
196+
197+
it('should support multiple window.addEventListener(unhandledrejection)', function(done) {
198+
if (!promiseUnhandleRejectionSupport()) {
199+
done();
200+
return;
201+
}
202+
Zone[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true;
203+
rootZone.fork({name: 'promise'}).run(function() {
204+
const listener1 = (evt: any) => {
205+
expect(evt.type).toEqual('unhandledrejection');
206+
expect(evt.promise.constructor.name).toEqual('Promise');
207+
expect(evt.reason.message).toBe('promise error');
208+
window.removeEventListener('unhandledrejection', listener1);
209+
};
210+
const listener2 = (evt: any) => {
211+
expect(evt.type).toEqual('unhandledrejection');
212+
expect(evt.promise.constructor.name).toEqual('Promise');
213+
expect(evt.reason.message).toBe('promise error');
214+
window.removeEventListener('unhandledrejection', listener2);
215+
done();
216+
};
217+
window.addEventListener('unhandledrejection', listener1);
218+
window.addEventListener('unhandledrejection', listener2);
219+
new Promise((resolve, reject) => {
220+
throw new Error('promise error');
221+
});
222+
});
223+
});
196224
});
197225
});
198226
});

test/node/process.spec.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ describe('process related test', () => {
2222
});
2323
});
2424
});
25-
it('process.nextTick should be excuted before macroTask and promise', (done) => {
25+
it('process.nextTick should be executed before macroTask and promise', (done) => {
2626
zoneA.run(function() {
2727
setTimeout(() => {
2828
result.push('timeout');
@@ -64,13 +64,16 @@ describe('process related test', () => {
6464
done();
6565
});
6666
});
67-
it('should support window.addEventListener(unhandledrejection)', function(done) {
67+
68+
it('should support process.on(unhandledRejection)', function(done) {
6869
const hookSpy = jasmine.createSpy('hook');
6970
Zone[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true;
7071
Zone.current.fork({name: 'promise'}).run(function() {
71-
process.on('unhandledRejection', function(reason, promise) {
72+
const listener = function(reason, promise) {
7273
hookSpy(promise, reason.message);
73-
});
74+
process.removeListener('unhandledRejection', listener);
75+
};
76+
process.on('unhandledRejection', listener);
7477
const p = new Promise((resolve, reject) => {
7578
throw new Error('promise error');
7679
});
@@ -82,13 +85,15 @@ describe('process related test', () => {
8285
});
8386
});
8487

85-
it('should support window.addEventListener(rejectionHandled)', function(done) {
88+
it('should support process.on(rejectionHandled)', function(done) {
8689
Zone[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true;
8790
Zone.current.fork({name: 'promise'}).run(function() {
88-
process.on('rejectionHandled', function(promise) {
91+
const listener = function(promise) {
8992
expect(promise).toEqual(p);
93+
process.removeListener('rejectionHandled', listener);
9094
done();
91-
});
95+
};
96+
process.on('rejectionHandled', listener);
9297
const p = new Promise((resolve, reject) => {
9398
throw new Error('promise error');
9499
});
@@ -98,4 +103,30 @@ describe('process related test', () => {
98103
}, 10);
99104
});
100105
});
106+
107+
it('should support multiple process.on(unhandledRejection)', function(done) {
108+
const hookSpy = jasmine.createSpy('hook');
109+
Zone[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true;
110+
Zone.current.fork({name: 'promise'}).run(function() {
111+
const listener1 = function(reason, promise) {
112+
hookSpy(promise, reason.message);
113+
process.removeListener('unhandledRejection', listener1);
114+
};
115+
const listener2 = function(reason, promise) {
116+
hookSpy(promise, reason.message);
117+
process.removeListener('unhandledRejection', listener2);
118+
};
119+
process.on('unhandledRejection', listener1);
120+
process.on('unhandledRejection', listener2);
121+
const p = new Promise((resolve, reject) => {
122+
throw new Error('promise error');
123+
});
124+
125+
setTimeout(function() {
126+
expect(hookSpy.calls.count()).toBe(2);
127+
expect(hookSpy.calls.allArgs()).toEqual([[p, 'promise error'], [p, 'promise error']]);
128+
done();
129+
}, 10);
130+
});
131+
});
101132
});

0 commit comments

Comments
 (0)