6
6
* @returns the rewritten service worker
7
7
*/
8
8
export const rewriteServiceWorker = ( body : Buffer ) => {
9
- function __cypressCreateListenerFunction ( listener ) {
9
+ function __cypressWrapListener ( listener : Function ) {
10
10
return ( event ) => {
11
11
// we want to override the respondWith method so we can track if it was called
12
12
// to determine if the service worker handled the request
@@ -28,50 +28,60 @@ export const rewriteServiceWorker = (body: Buffer) => {
28
28
}
29
29
}
30
30
31
- function __cypressOverwriteAddRemoveEventListener ( ) {
32
- const _listeners = new WeakMap ( )
33
- const _capturedListeners = new WeakMap ( )
34
- const _handleEvents = new WeakMap ( )
31
+ function __cypressOverwriteAddRemoveEventListeners ( ) {
32
+ const _nonCaptureListenersMap = new WeakMap < EventListenerOrEventListenerObject , EventListenerOrEventListenerObject > ( )
33
+ const _captureListenersMap = new WeakMap < EventListenerOrEventListenerObject , EventListenerOrEventListenerObject > ( )
34
+ const _handleEventsMap = new WeakMap < Object , EventListenerOrEventListenerObject > ( )
35
35
36
- const canWrapListener = ( listener ) => {
36
+ // A listener is considered valid if it is a function, an object with a handleEvent method, or an object (the handleEvent function could be added later)
37
+ const isValidListener = ( listener : EventListenerOrEventListenerObject ) => {
37
38
return typeof listener === 'function' || listener ?. handleEvent || typeof listener === 'object'
38
39
}
39
40
41
+ // Get the capture value from the options
42
+ const getCaptureValue = ( options ?: boolean | AddEventListenerOptions ) => {
43
+ return typeof options === 'boolean' ? options : options ?. capture
44
+ }
45
+
40
46
const oldAddEventListener = self . addEventListener
41
47
42
- // Overwrite the addEventListener method so we can
43
- // determine if the service worker handled the request
48
+ // Overwrite the addEventListener method so we can determine if the service worker handled the request
49
+ // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
44
50
self . addEventListener = ( type : string , listener : EventListenerOrEventListenerObject , options ?: boolean | AddEventListenerOptions ) => {
45
- if ( type === 'fetch' && canWrapListener ( listener ) ) {
51
+ if ( type === 'fetch' && isValidListener ( listener ) ) {
46
52
let newListener
47
53
48
54
// If the listener is a function, we can just wrap it
49
55
// If the listener is an object with a handleEvent method, we can wrap that method
50
56
// Otherwise, we need to wrap the listener in a proxy so we can track and wrap the handleEvent function
51
57
if ( typeof listener === 'function' ) {
52
- newListener = __cypressCreateListenerFunction ( listener )
58
+ newListener = __cypressWrapListener ( listener )
53
59
} else if ( listener ?. handleEvent ) {
54
- newListener = __cypressCreateListenerFunction ( listener . handleEvent )
60
+ newListener = __cypressWrapListener ( listener . handleEvent )
55
61
listener . handleEvent = newListener
56
62
} else {
63
+ // since the handleEvent function is being lazily created, we need to use a proxy to wrap it
57
64
newListener = new Proxy ( listener , {
58
65
get ( target , key ) {
59
66
if ( key === 'handleEvent' ) {
60
- if ( ! _handleEvents . has ( target ) ) {
61
- _handleEvents . set ( target , __cypressCreateListenerFunction ( target . handleEvent ) )
67
+ const values = _handleEventsMap . get ( target )
68
+
69
+ if ( ! values ) {
70
+ // TODO: also check if the handleEvent function has changed
71
+ _handleEventsMap . set ( target , __cypressWrapListener ( target . handleEvent ) )
62
72
}
63
73
64
- return _handleEvents . get ( target )
74
+ return _handleEventsMap . get ( target )
65
75
}
66
76
67
77
return Reflect . get ( target , key )
68
78
} ,
69
79
} )
70
80
}
71
81
72
- const capture = typeof options === 'boolean' ? options : options ?. capture
73
-
74
- capture ? _capturedListeners . set ( listener , newListener ) : _listeners . set ( listener , newListener )
82
+ // get the capture value so we know which map to add the listener to
83
+ // so we can then remove the listener later if requested
84
+ getCaptureValue ( options ) ? _captureListenersMap . set ( listener , newListener ) : _nonCaptureListenersMap . set ( listener , newListener )
75
85
76
86
return oldAddEventListener ( type , newListener , options )
77
87
}
@@ -81,20 +91,22 @@ export const rewriteServiceWorker = (body: Buffer) => {
81
91
82
92
const oldRemoveEventListener = self . removeEventListener
83
93
84
- // Overwrite the removeEventListener method so we can
85
- // remove the listener from the map
94
+ // Overwrite the removeEventListener method so we can remove the listener from the map
95
+ // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
86
96
self . removeEventListener = ( type : string , listener : EventListenerOrEventListenerObject , options ?: boolean | AddEventListenerOptions ) => {
87
- if ( type === 'fetch' && canWrapListener ( listener ) ) {
88
- const capture = typeof options === 'boolean' ? options : options ?. capture
89
- const newListener = capture ? _capturedListeners . get ( listener ) : _listeners . get ( listener )
97
+ if ( type === 'fetch' && isValidListener ( listener ) ) {
98
+ // get the capture value so we know which map to remove the listener from
99
+ const capture = getCaptureValue ( options )
100
+ const newListener = capture ? _captureListenersMap . get ( listener ) : _nonCaptureListenersMap . get ( listener )
90
101
91
- capture ? _capturedListeners . delete ( listener ) : _listeners . delete ( listener )
102
+ capture ? _captureListenersMap . delete ( listener ) : _nonCaptureListenersMap . delete ( listener )
92
103
104
+ // If the listener is an object with a handleEvent method, we need to remove the wrapped function
93
105
if ( typeof listener === 'object' && typeof listener . handleEvent === 'function' ) {
94
- _handleEvents . delete ( listener )
106
+ _handleEventsMap . delete ( listener )
95
107
}
96
108
97
- return oldRemoveEventListener ( type , newListener , options )
109
+ return oldRemoveEventListener ( type , newListener ! , options )
98
110
}
99
111
100
112
return oldRemoveEventListener ( type , listener , options )
@@ -126,7 +138,7 @@ export const rewriteServiceWorker = (body: Buffer) => {
126
138
let newHandler
127
139
128
140
if ( value ) {
129
- newHandler = __cypressCreateListenerFunction ( value )
141
+ newHandler = __cypressWrapListener ( value )
130
142
}
131
143
132
144
originalPropertyDescriptor . set ?. call ( this , newHandler )
@@ -136,8 +148,8 @@ export const rewriteServiceWorker = (body: Buffer) => {
136
148
}
137
149
138
150
const updatedBody = `
139
- ${ __cypressCreateListenerFunction } ;
140
- (${ __cypressOverwriteAddRemoveEventListener } )();
151
+ ${ __cypressWrapListener } ;
152
+ (${ __cypressOverwriteAddRemoveEventListeners } )();
141
153
(${ __cypressOverwriteOnfetch } )();
142
154
${ body } `
143
155
0 commit comments