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

Commit e9536ec

Browse files
JiaLiPassionmhevery
authored andcommitted
fix(event): should pass boolean to addEventListener if not support passive (#1053)
1 parent 0720d79 commit e9536ec

2 files changed

Lines changed: 89 additions & 4 deletions

File tree

‎lib/common/events.ts‎

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,23 @@ interface EventTaskData extends TaskData {
1818
readonlyuseG?: boolean;
1919
}
2020

21+
letpassiveSupported=false;
22+
23+
if(typeofwindow!=='undefined'){
24+
try{
25+
constoptions=Object.defineProperty({},'passive',{
26+
get: function(){
27+
passiveSupported=true;
28+
}
29+
});
30+
31+
window.addEventListener('test',options,options);
32+
window.removeEventListener('test',options,options);
33+
}catch(err){
34+
passiveSupported=false;
35+
}
36+
}
37+
2138
// an identifier to tell ZoneTask do not create a new invoke closure
2239
constOPTIMIZED_ZONE_EVENT_TASK_DATA: EventTaskData={
2340
useG: true
@@ -50,6 +67,8 @@ export interface PatchEventTargetOptions {
5067
rt?: boolean;
5168
// event compare handler
5269
diff?: (task: any,delegate: any)=>boolean;
70+
// support passive or not
71+
supportPassive?: boolean;
5372
}
5473

5574
exportfunctionpatchEventTarget(
@@ -212,12 +231,25 @@ export function patchEventTarget(
212231
proto[patchOptions.prepend];
213232
}
214233

215-
constcustomScheduleGlobal=function(){
234+
functioncheckIsPassive(task: Task){
235+
if(!passiveSupported&&typeoftaskData.options!=='boolean'&&
236+
typeoftaskData.options!=='undefined'&&taskData.options!==null){
237+
// options is a non-null non-undefined object
238+
// passive is not supported
239+
// don't pass options as object
240+
// just pass capture as a boolean
241+
(taskasany).options=!!taskData.options.capture;
242+
taskData.options=(taskasany).options;
243+
}
244+
}
245+
246+
constcustomScheduleGlobal=function(task: Task){
216247
// if there is already a task for the eventName + capture,
217248
// just return, because we use the shared globalZoneAwareCallback here.
218249
if(taskData.isExisting){
219250
return;
220251
}
252+
checkIsPassive(task);
221253
returnnativeAddEventListener.call(
222254
taskData.target,taskData.eventName,
223255
taskData.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback,
@@ -265,6 +297,7 @@ export function patchEventTarget(
265297
};
266298

267299
constcustomScheduleNonGlobal=function(task: Task){
300+
checkIsPassive(task);
268301
returnnativeAddEventListener.call(
269302
taskData.target,taskData.eventName,task.invoke,taskData.options);
270303
};
@@ -421,7 +454,11 @@ export function patchEventTarget(
421454
if(once){
422455
options.once=true;
423456
}
424-
task.options=options;
457+
if(!(!passiveSupported&&typeoftask.options==='boolean')){
458+
// if not support passive, and we pass an option object
459+
// to addEventListener, we should save the options to task
460+
task.options=options;
461+
}
425462
task.target=target;
426463
task.capture=capture;
427464
task.eventName=eventName;

‎test/browser/browser.spec.ts‎

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ try {
4747
supportsPassive=true;
4848
}
4949
});
50-
window.addEventListener('test',nullasany,opts);
51-
window.removeEventListener('test',nullasany,opts);
50+
window.addEventListener('test',optsasany,opts);
51+
window.removeEventListener('test',optsasany,opts);
5252
}catch(e){
5353
}
5454

@@ -75,6 +75,14 @@ function ieOrEdge() {
7575

7676
(ieOrEdgeasany).message='IE/Edge Test';
7777

78+
classTestEventListener{
79+
logs: string[]=[];
80+
addEventListener(eventName: string,listener: any,options: any){
81+
this.logs.push(options);
82+
}
83+
removeEventListener(eventName: string,listener: any,options: any){}
84+
}
85+
7886
describe('Zone',function(){
7987
constrootZone=Zone.current;
8088
(Zoneasany)[zoneSymbol('ignoreConsoleErrorUncaughtError')]=true;
@@ -996,6 +1004,46 @@ describe('Zone', function() {
9961004
expect(logs).toEqual(['click']);
9971005
}));
9981006

1007+
it('should change options to boolean if not support passive',()=>{
1008+
patchEventTarget(window,[TestEventListener.prototype]);
1009+
consttestEventListener=newTestEventListener();
1010+
1011+
constlistener=function(){};
1012+
testEventListener.addEventListener('test',listener,{passive: true});
1013+
testEventListener.addEventListener('test1',listener,{once: true});
1014+
testEventListener.addEventListener('test2',listener,{capture: true});
1015+
testEventListener.addEventListener('test3',listener,{passive: false});
1016+
testEventListener.addEventListener('test4',listener,{once: false});
1017+
testEventListener.addEventListener('test5',listener,{capture: false});
1018+
if(!supportsPassive){
1019+
expect(testEventListener.logs).toEqual([false,false,true,false,false,false]);
1020+
}else{
1021+
expect(testEventListener.logs).toEqual([
1022+
{passive: true},{once: true},{capture: true},{passive: false},{once: false},
1023+
{capture: false}
1024+
]);
1025+
}
1026+
});
1027+
1028+
it('should change options to boolean if not support passive on HTMLElement',()=>{
1029+
constlogs: string[]=[];
1030+
constlistener=(e: Event)=>{
1031+
logs.push('clicked');
1032+
};
1033+
1034+
(buttonasany).addEventListener('click',listener,{once: true});
1035+
button.dispatchEvent(clickEvent);
1036+
expect(logs).toEqual(['clicked']);
1037+
button.dispatchEvent(clickEvent);
1038+
if(supportsPassive){
1039+
expect(logs).toEqual(['clicked']);
1040+
}else{
1041+
expect(logs).toEqual(['clicked','clicked']);
1042+
}
1043+
1044+
button.removeEventListener('click',listener);
1045+
});
1046+
9991047
it('should support addEventListener with AddEventListenerOptions passive setting',
10001048
ifEnvSupports(supportEventListenerOptions,function(){
10011049
consthookSpy=jasmine.createSpy('hook');

0 commit comments

Comments
 (0)