@@ -7,7 +7,8 @@ let messageIDs = 0;
7
7
const MSGTYPE_QUERY = 0 ;
8
8
const MSGTYPE_RESPONSE = 1 ;
9
9
const MSGTYPE_HOST_ID = 2 ;
10
- const MSGTYPES = [ MSGTYPE_QUERY , MSGTYPE_RESPONSE , MSGTYPE_HOST_ID ] ;
10
+ const MSGTYPE_HOST_CLOSE = 3 ;
11
+ const MSGTYPES = [ MSGTYPE_QUERY , MSGTYPE_RESPONSE , MSGTYPE_HOST_ID , MSGTYPE_HOST_CLOSE ] ;
11
12
12
13
// Inlined from https://github.com/then/is-promise
13
14
const isPromise = obj => ! ! obj && ( typeof obj === 'object' || typeof obj === 'function' ) && typeof obj . then === 'function' ;
@@ -63,6 +64,17 @@ class PromiseWorker {
63
64
64
65
worker . port . addEventListener ( 'message' , this . _onMessage ) ;
65
66
worker . port . start ( ) ;
67
+
68
+ // Handle tab close. This isn't perfect, but there is no perfect method
69
+ // http://stackoverflow.com/q/13662089/786644 and this should work like
70
+ // 99% of the time. It is a memory leak if it fails, but for most use
71
+ // cases, it shouldn't be noticeable.
72
+ window . addEventListener ( 'beforeunload' , ( ) => {
73
+ // Prevent firing if we don't know hostID yet
74
+ if ( this . _hostID !== undefined ) {
75
+ this . _postMessageBi ( [ MSGTYPE_HOST_CLOSE , - 1 , this . _hostID ] ) ;
76
+ }
77
+ } ) ;
66
78
}
67
79
68
80
this . _worker = worker ;
@@ -77,6 +89,7 @@ class PromiseWorker {
77
89
_postMessageBi ( obj : any [ ] , targetHostID : number | void ) {
78
90
// console.log('_postMessageBi', obj, targetHostID);
79
91
if ( ! this . _worker && this . _workerType === 'SharedWorker' ) {
92
+ // If targetHostID has been deleted, this will do nothing, which is fine I think
80
93
this . _hosts . forEach ( ( { port } , hostID ) => {
81
94
if ( targetHostID === undefined || targetHostID === hostID ) {
82
95
port . postMessage ( obj ) ;
@@ -195,15 +208,26 @@ class PromiseWorker {
195
208
callback ( errorMsg , result ) ;
196
209
} else if ( type === MSGTYPE_HOST_ID ) {
197
210
if ( this . _worker === undefined ) {
198
- throw new Error ( 'hostID can only be sent to a host' ) ;
211
+ throw new Error ( 'MSGTYPE_HOST_ID can only be sent to a host' ) ;
199
212
}
200
213
201
- if ( typeof message [ 2 ] !== 'number' ) {
214
+ if ( message [ 2 ] !== undefined && typeof message [ 2 ] !== 'number' ) {
202
215
throw new Error ( 'Invalid hostID' ) ;
203
216
}
204
217
const hostID : number | void = message [ 2 ] ;
205
218
206
219
this . _hostID = hostID ;
220
+ } else if ( type === MSGTYPE_HOST_CLOSE ) {
221
+ if ( this . _worker !== undefined ) {
222
+ throw new Error ( 'MSGTYPE_HOST_CLOSE can only be sent to a worker' ) ;
223
+ }
224
+
225
+ if ( typeof message [ 2 ] !== 'number' ) {
226
+ throw new Error ( 'Invalid hostID' ) ;
227
+ }
228
+ const hostID : number = message [ 2 ] ;
229
+
230
+ this . _hosts . delete ( hostID ) ;
207
231
}
208
232
}
209
233
}
0 commit comments