promise-worker-bi 4.1.1 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@ This is based on [promise-worker](https://github.com/nolanlawson/promise-worker)
8
8
 
9
9
  Install:
10
10
 
11
- yarn add promise-worker-bi
11
+ npm install promise-worker-bi
12
12
 
13
13
  Inside your main bundle:
14
14
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- declare type ErrorCallback = (a: Error) => void;
2
- declare type QueryCallback = (a: any[], b: number | undefined) => any;
1
+ type ErrorCallback = (a: Error) => void;
2
+ type QueryCallback = (a: any[], b: number | undefined) => any;
3
3
  declare abstract class PWBBase {
4
4
  _callbacks: Map<number, (a: Error | null, b: any) => void>;
5
5
  _queryCallback: QueryCallback;
@@ -4,96 +4,82 @@ const MSGTYPE_RESPONSE = 1;
4
4
  const MSGTYPE_HOST_ID = 2;
5
5
  const MSGTYPE_HOST_CLOSE = 3;
6
6
  const MSGTYPE_WORKER_ERROR = 4;
7
- const MSGTYPES = [MSGTYPE_QUERY, MSGTYPE_RESPONSE, MSGTYPE_HOST_ID, MSGTYPE_HOST_CLOSE, MSGTYPE_WORKER_ERROR]; // Inlined from https://github.com/then/is-promise
7
+ const MSGTYPES = [MSGTYPE_QUERY, MSGTYPE_RESPONSE, MSGTYPE_HOST_ID, MSGTYPE_HOST_CLOSE, MSGTYPE_WORKER_ERROR];
8
8
 
9
+ // Inlined from https://github.com/then/is-promise
9
10
  const isPromise = obj => !!obj && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function";
10
-
11
11
  const toFakeError = error => {
12
12
  const fakeError = {
13
13
  name: error.name,
14
14
  message: error.message
15
15
  };
16
-
17
16
  if (typeof error.stack === "string") {
18
17
  fakeError.stack = error.stack;
19
- } // These are non-standard properties, I think only in some versions of Firefox
20
- // @ts-expect-error
21
-
18
+ }
22
19
 
20
+ // These are non-standard properties, I think only in some versions of Firefox
21
+ // @ts-expect-error
23
22
  if (typeof error.fileName === "string") {
24
23
  // @ts-expect-error
25
24
  fakeError.fileName = error.fileName;
26
- } // @ts-expect-error
27
-
28
-
25
+ }
26
+ // @ts-expect-error
29
27
  if (typeof error.columnNumber === "number") {
30
28
  // @ts-expect-error
31
29
  fakeError.columnNumber = error.columnNumber;
32
- } // @ts-expect-error
33
-
34
-
30
+ }
31
+ // @ts-expect-error
35
32
  if (typeof error.lineNumber === "number") {
36
33
  // @ts-expect-error
37
34
  fakeError.lineNumber = error.lineNumber;
38
35
  }
39
-
40
36
  return fakeError;
41
- }; // Object rather than FakeError for convenience
42
-
37
+ };
43
38
 
39
+ // Object rather than FakeError for convenience
44
40
  const fromFakeError = fakeError => {
45
41
  const error = new Error();
46
42
  return Object.assign(error, fakeError);
47
43
  };
48
-
49
44
  const logError = err => {
50
45
  // Logging in the console makes debugging in the worker easier
51
-
52
- /* eslint-disable no-console */
53
46
  console.error("Error in Worker:");
54
47
  console.error(err); // Safari needs it on new line
55
-
56
- /* eslint-enable no-console */
57
48
  };
58
-
59
49
  class PWBBase {
60
50
  constructor() {
61
51
  // console.log('constructor', worker);
62
- this._callbacks = new Map(); // eslint-disable-next-line @typescript-eslint/no-empty-function
63
-
64
- this._queryCallback = () => {}; // @ts-expect-error
65
-
52
+ this._callbacks = new Map();
53
+ this._queryCallback = () => {};
66
54
 
55
+ // @ts-expect-error
67
56
  this._onMessage = this._onMessage.bind(this);
68
57
  }
69
-
70
58
  register(cb) {
71
59
  // console.log('register', cb);
72
60
  this._queryCallback = cb;
73
- } // From worker, 2nd param could be hostID if sending to specific host. From UI, 2nd param could be an array of transferable objects
61
+ }
74
62
 
63
+ // From worker, 2nd param could be hostID if sending to specific host. From UI, 2nd param could be an array of transferable objects
75
64
 
76
65
  _postResponse(messageID, error, result, hostID) {
77
66
  // console.log('_postResponse', messageID, error, result);
78
67
  if (error) {
79
68
  logError(error);
80
-
81
69
  this._postMessage([MSGTYPE_RESPONSE, messageID, toFakeError(error)], hostID);
82
70
  } else {
83
71
  // Hackily identify when message contains transferable objects
84
- if (typeof result === "object" && result !== null && result.hasOwnProperty("message") && result.hasOwnProperty("_PWB_TRANSFER")) {
72
+ if (typeof result === "object" && result !== null && Object.hasOwn(result, "message") && Object.hasOwn(result, "_PWB_TRANSFER")) {
85
73
  this._postMessage([MSGTYPE_RESPONSE, messageID, null, result.message], hostID, result._PWB_TRANSFER);
86
74
  } else {
87
75
  this._postMessage([MSGTYPE_RESPONSE, messageID, null, result], hostID);
88
76
  }
89
77
  }
90
78
  }
91
-
92
79
  _handleQuery(messageID, query, hostID) {
93
80
  // console.log('_handleQuery', messageID, query);
94
81
  try {
95
82
  const result = this._queryCallback(query, hostID);
96
-
97
83
  if (!isPromise(result)) {
98
84
  this._postResponse(messageID, null, result, hostID);
99
85
  } else {
@@ -106,78 +92,61 @@ class PWBBase {
106
92
  } catch (err) {
107
93
  this._postResponse(messageID, err);
108
94
  }
109
- } // Either return messageID and type if further processing is needed, or undefined otherwise
110
-
95
+ }
111
96
 
97
+ // Either return messageID and type if further processing is needed, or undefined otherwise
112
98
  _onMessageCommon(e) {
113
- // eslint-disable-line no-undef
114
99
  // console.log('_onMessage', e.data);
115
100
  const message = e.data;
116
-
117
101
  if (!Array.isArray(message) || message.length < 3 || message.length > 4) {
118
102
  return; // Ignore - this message is not for us
119
103
  }
120
-
121
104
  if (typeof message[0] !== "number" || MSGTYPES.indexOf(message[0]) < 0) {
122
105
  throw new Error("Invalid messageID");
123
106
  }
124
-
125
107
  const type = message[0];
126
-
127
108
  if (typeof message[1] !== "number") {
128
109
  throw new Error("Invalid messageID");
129
110
  }
130
-
131
111
  const messageID = message[1];
132
-
133
112
  if (type === MSGTYPE_QUERY) {
134
113
  const query = message[2];
135
-
136
114
  if (typeof message[3] !== "number" && message[3] !== undefined) {
137
115
  throw new Error("Invalid hostID");
138
116
  }
139
-
140
117
  const hostID = message[3];
141
-
142
118
  this._handleQuery(messageID, query, hostID);
143
-
144
119
  return;
145
120
  }
146
-
147
121
  if (type === MSGTYPE_RESPONSE) {
148
122
  if (message[2] !== null && typeof message[2] !== "object") {
149
123
  throw new Error("Invalid error");
150
124
  }
151
-
152
125
  const error = message[2] === null ? null : fromFakeError(message[2]);
153
126
  const result = message[3];
154
-
155
127
  const callback = this._callbacks.get(messageID);
156
-
157
128
  if (callback === undefined) {
158
129
  // Ignore - user might have created multiple PromiseWorkers.
159
130
  // This message is not for us.
160
131
  return;
161
132
  }
162
-
163
133
  this._callbacks.delete(messageID);
164
-
165
134
  callback(error, result);
166
135
  return;
167
136
  }
168
-
169
137
  return {
170
138
  message,
171
139
  type
172
140
  };
173
141
  }
174
-
175
142
  }
176
-
177
143
  class PWBHost extends PWBBase {
178
144
  // Only defined on host
145
+
179
146
  constructor(worker) {
180
- super(); // The following if statement used to check `worker instanceof Worker` but I have recieved
147
+ super();
148
+
149
+ // The following if statement used to check `worker instanceof Worker` but I have recieved
181
150
  // reports that in some weird cases, Safari will inappropriately return false for that, even
182
151
  // in obvious cases like:
183
152
  //
@@ -187,21 +156,23 @@ class PWBHost extends PWBBase {
187
156
  //
188
157
  // So instead, let's do this test for worker.port which only exists on shared workers.
189
158
  // @ts-expect-error
190
-
191
159
  if (worker.port === undefined) {
192
- this._workerType = "Worker"; // @ts-expect-error
160
+ this._workerType = "Worker";
193
161
 
162
+ // @ts-expect-error
194
163
  worker.addEventListener("message", this._onMessage);
195
164
  } else {
196
- this._workerType = "SharedWorker"; // @ts-expect-error - it doesn't know if _worker is Worker or SharedWorker, but I do
165
+ this._workerType = "SharedWorker";
197
166
 
198
- worker.port.addEventListener("message", this._onMessage); // @ts-expect-error - it doesn't know if _worker is Worker or SharedWorker, but I do
167
+ // @ts-expect-error - it doesn't know if _worker is Worker or SharedWorker, but I do
168
+ worker.port.addEventListener("message", this._onMessage);
169
+ // @ts-expect-error - it doesn't know if _worker is Worker or SharedWorker, but I do
170
+ worker.port.start();
199
171
 
200
- worker.port.start(); // Handle tab close. This isn't perfect, but there is no perfect method
172
+ // Handle tab close. This isn't perfect, but there is no perfect method
201
173
  // http://stackoverflow.com/q/13662089/786644 and this should work like
202
174
  // 99% of the time. It is a memory leak if it fails, but for most use
203
175
  // cases, it shouldn't be noticeable.
204
-
205
176
  window.addEventListener("beforeunload", () => {
206
177
  // Prevent firing if we don't know hostID yet
207
178
  if (this._hostID !== undefined) {
@@ -209,22 +180,20 @@ class PWBHost extends PWBBase {
209
180
  }
210
181
  });
211
182
  }
212
-
213
183
  this._worker = worker;
214
184
  this._hostIDQueue = [];
215
185
  }
216
-
217
186
  registerError(cb) {
218
187
  // console.log('registerError', cb);
219
- this._errorCallback = cb; // Some browsers (Firefox) call onerror on every host, while others
220
- // (Chrome) do nothing. Let's disable that everywhere, for consistency.
188
+ this._errorCallback = cb;
221
189
 
190
+ // Some browsers (Firefox) call onerror on every host, while others
191
+ // (Chrome) do nothing. Let's disable that everywhere, for consistency.
222
192
  this._worker.addEventListener("error", e => {
223
193
  e.preventDefault();
224
194
  e.stopPropagation();
225
195
  });
226
196
  }
227
-
228
197
  _postMessage(obj, _hostID, transfer) {
229
198
  // console.log('_postMessage', obj, _hostID, transfer);
230
199
  if (this._workerType === "Worker") {
@@ -237,14 +206,12 @@ class PWBHost extends PWBBase {
237
206
  throw new Error("WTF");
238
207
  }
239
208
  }
240
-
241
209
  postMessage(userMessage, _hostID, transfer) {
242
210
  // console.log('postMessage', userMessage, _hostID, transfer);
243
211
  const actuallyPostMessage = (resolve, reject) => {
244
212
  const messageID = messageIDs;
245
213
  messageIDs += 1;
246
214
  const messageToSend = [MSGTYPE_QUERY, messageID, userMessage, this._hostID];
247
-
248
215
  this._callbacks.set(messageID, (error, result) => {
249
216
  if (error) {
250
217
  reject(error);
@@ -252,10 +219,8 @@ class PWBHost extends PWBBase {
252
219
  resolve(result);
253
220
  }
254
221
  });
255
-
256
222
  this._postMessage(messageToSend, undefined, transfer);
257
223
  };
258
-
259
224
  return new Promise((resolve, reject) => {
260
225
  // Don't send a message until hostID is known, otherwise it's a race
261
226
  // condition and sometimes hostID will be undefined.
@@ -268,25 +233,21 @@ class PWBHost extends PWBBase {
268
233
  }
269
234
  });
270
235
  }
271
-
272
236
  _onMessage(e) {
273
237
  const common = this._onMessageCommon(e);
274
-
275
238
  if (!common) {
276
239
  return;
277
240
  }
278
-
279
- const message = common.message,
280
- type = common.type;
281
-
241
+ const {
242
+ message,
243
+ type
244
+ } = common;
282
245
  if (type === MSGTYPE_HOST_ID) {
283
246
  if (message[2] !== undefined && typeof message[2] !== "number") {
284
247
  throw new Error("Invalid hostID");
285
248
  }
286
-
287
249
  const hostID = message[2];
288
250
  this._hostID = hostID;
289
-
290
251
  if (this._hostIDQueue !== undefined) {
291
252
  this._hostIDQueue.forEach(func => {
292
253
  // Not entirely sure why setTimeout is needed, might be just for unit tests
@@ -294,74 +255,68 @@ class PWBHost extends PWBBase {
294
255
  func();
295
256
  }, 0);
296
257
  });
297
-
298
258
  this._hostIDQueue = undefined; // Never needed again after initial setup
299
259
  }
300
260
  } else if (type === MSGTYPE_WORKER_ERROR) {
301
261
  if (message[2] !== undefined && message[2] !== null && typeof message[2] === "object") {
302
262
  const error = fromFakeError(message[2]);
303
-
304
263
  if (this._errorCallback !== undefined) {
305
264
  this._errorCallback(error);
306
265
  }
307
266
  }
308
267
  }
309
268
  }
310
-
311
269
  }
312
-
313
270
  class PWBWorker extends PWBBase {
314
271
  constructor() {
315
- super(); // Only actually used for SharedWorker
272
+ super();
316
273
 
274
+ // Only actually used for SharedWorker
317
275
  this._hosts = new Map();
318
276
  this._maxHostID = -1;
319
-
320
- if ( // @ts-expect-error
321
- typeof SharedWorkerGlobalScope !== "undefined" && // @ts-expect-error
277
+ if (
278
+ // @ts-expect-error
279
+ typeof SharedWorkerGlobalScope !== "undefined" &&
280
+ // @ts-expect-error
322
281
  self instanceof SharedWorkerGlobalScope) {
323
282
  this._workerType = "SharedWorker";
324
283
  self.addEventListener("connect", e => {
325
284
  // @ts-expect-error
326
285
  const port = e.ports[0];
327
- port.addEventListener("message", e2 => this._onMessage(e2)); // eslint-disable-line no-undef
328
-
286
+ port.addEventListener("message", e2 => this._onMessage(e2));
329
287
  port.start();
330
288
  this._maxHostID += 1;
331
289
  const hostID = this._maxHostID;
332
-
333
290
  this._hosts.set(hostID, {
334
291
  port
335
- }); // Send back hostID to this host, otherwise it has no way to know it
336
-
292
+ });
337
293
 
294
+ // Send back hostID to this host, otherwise it has no way to know it
338
295
  this._postMessage([MSGTYPE_HOST_ID, -1, hostID], hostID);
339
296
  });
340
297
  self.addEventListener("error", e => {
341
- logError(e.error); // Just send to first host, so as to not duplicate error tracking
298
+ logError(e.error);
342
299
 
300
+ // Just send to first host, so as to not duplicate error tracking
343
301
  const hostID = this._hosts.keys().next().value;
344
-
345
302
  if (hostID !== undefined) {
346
303
  this._postMessage([MSGTYPE_WORKER_ERROR, -1, toFakeError(e.error)], hostID);
347
304
  }
348
305
  });
349
306
  } else {
350
307
  this._workerType = "Worker";
351
- self.addEventListener("message", this._onMessage); // Since this is not a Shared Worker, hostID is always 0 so it's not strictly required to
308
+ self.addEventListener("message", this._onMessage);
309
+
310
+ // Since this is not a Shared Worker, hostID is always 0 so it's not strictly required to
352
311
  // send this back, but it makes the API a bit more consistent if there is the same
353
312
  // initialization handshake in both cases.
354
-
355
313
  this._postMessage([MSGTYPE_HOST_ID, -1, 0], 0);
356
-
357
314
  self.addEventListener("error", e => {
358
315
  logError(e.error);
359
-
360
316
  this._postMessage([MSGTYPE_WORKER_ERROR, -1, toFakeError(e.error)]);
361
317
  });
362
318
  }
363
319
  }
364
-
365
320
  _postMessage(obj, targetHostID, transfer) {
366
321
  // console.log('_postMessage', obj, targetHostID);
367
322
  if (this._workerType === "SharedWorker") {
@@ -381,14 +336,12 @@ class PWBWorker extends PWBBase {
381
336
  throw new Error("WTF");
382
337
  }
383
338
  }
384
-
385
339
  postMessage(userMessage, targetHostID, transfer) {
386
340
  // console.log('postMessage', userMessage, targetHostID);
387
341
  const actuallyPostMessage = (resolve, reject) => {
388
342
  const messageID = messageIDs;
389
343
  messageIDs += 1;
390
344
  const messageToSend = [MSGTYPE_QUERY, messageID, userMessage];
391
-
392
345
  this._callbacks.set(messageID, (error, result) => {
393
346
  if (error) {
394
347
  reject(error);
@@ -396,36 +349,29 @@ class PWBWorker extends PWBBase {
396
349
  resolve(result);
397
350
  }
398
351
  });
399
-
400
352
  this._postMessage(messageToSend, targetHostID, transfer);
401
353
  };
402
-
403
354
  return new Promise((resolve, reject) => {
404
355
  actuallyPostMessage(resolve, reject);
405
356
  });
406
357
  }
407
-
408
358
  _onMessage(e) {
409
359
  const common = this._onMessageCommon(e);
410
-
411
360
  if (!common) {
412
361
  return;
413
362
  }
414
-
415
- const message = common.message,
416
- type = common.type;
417
-
363
+ const {
364
+ message,
365
+ type
366
+ } = common;
418
367
  if (type === MSGTYPE_HOST_CLOSE) {
419
368
  if (typeof message[2] !== "number") {
420
369
  throw new Error("Invalid hostID");
421
370
  }
422
-
423
371
  const hostID = message[2];
424
-
425
372
  this._hosts.delete(hostID);
426
373
  }
427
374
  }
428
-
429
375
  }
430
376
 
431
377
  export { PWBHost, PWBWorker };