@webqit/port-plus 0.1.14 → 0.1.15
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 +102 -116
- package/dist/main.js +1 -1
- package/dist/main.js.map +3 -3
- package/package.json +3 -3
- package/src/BroadcastChannelPlus.js +12 -2
- package/src/MessageChannelPlus.js +2 -2
- package/src/MessageEventPlus.js +1 -2
- package/src/MessagePortPlus.js +88 -87
- package/src/StarPort.js +37 -24
- package/src/WebSocketPort.js +24 -12
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
],
|
|
15
15
|
"homepage": "https://port-plus.netlify.app/",
|
|
16
16
|
"icon": "https://webqit.io/icon.svg",
|
|
17
|
-
"version": "0.1.
|
|
17
|
+
"version": "0.1.15",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"@webqit/util": "^0.8.16"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@webqit/observer": "^3.8.
|
|
41
|
+
"@webqit/observer": "^3.8.19"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@webqit/observer": "^3.8.
|
|
44
|
+
"@webqit/observer": "^3.8.19",
|
|
45
45
|
"chai": "^4.3.4",
|
|
46
46
|
"chai-as-promised": "^7.1.1",
|
|
47
47
|
"esbuild": "^0.20.2",
|
|
@@ -4,19 +4,29 @@ import {
|
|
|
4
4
|
} from './MessagePortPlus.js';
|
|
5
5
|
|
|
6
6
|
export class BroadcastChannelPlus extends MessagePortPlusMockPortsMixin(BroadcastChannel) {
|
|
7
|
-
constructor(name, {
|
|
7
|
+
constructor(name, { handshake = 0, postAwaitsOpen = false, clientServerMode = null, autoClose = false } = {}) {
|
|
8
8
|
super(name);
|
|
9
9
|
|
|
10
10
|
const portPlusMeta = _meta(this);
|
|
11
11
|
|
|
12
|
+
if (typeof handshake !== 'number') {
|
|
13
|
+
throw new Error('handshake must be a number');
|
|
14
|
+
}
|
|
15
|
+
if (handshake < 0 || handshake > 2) {
|
|
16
|
+
throw new Error('handshake must be between 0 and 2');
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
if (clientServerMode
|
|
13
20
|
&& !['server', 'client'].includes(clientServerMode)) {
|
|
14
21
|
throw new Error('clientServerMode must be "server" or "client"');
|
|
15
22
|
}
|
|
16
|
-
|
|
23
|
+
|
|
24
|
+
portPlusMeta.set('options', { handshake, postAwaitsOpen, clientServerMode, autoClose });
|
|
17
25
|
// Must come before upgradeEvents()
|
|
18
26
|
|
|
19
27
|
this.constructor/* IMPORTANT */.upgradeEvents(this);
|
|
28
|
+
|
|
29
|
+
if (handshake === 0) this.start();
|
|
20
30
|
}
|
|
21
31
|
|
|
22
32
|
__postMessage(payload, portOptions) {
|
|
@@ -2,10 +2,10 @@ import { MessagePortPlus } from './MessagePortPlus.js';
|
|
|
2
2
|
|
|
3
3
|
export class MessageChannelPlus extends MessageChannel {
|
|
4
4
|
|
|
5
|
-
constructor({
|
|
5
|
+
constructor({ handshake = 0, postAwaitsOpen = false } = {}) {
|
|
6
6
|
super();
|
|
7
7
|
[this.port1, this.port2].forEach((port, i) => {
|
|
8
|
-
MessagePortPlus.upgradeInPlace(port, {
|
|
8
|
+
MessagePortPlus.upgradeInPlace(port, { handshake, postAwaitsOpen });
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
}
|
package/src/MessageEventPlus.js
CHANGED
|
@@ -50,8 +50,7 @@ export class MessageEventPlus extends MessageEvent {
|
|
|
50
50
|
this.#honourDoneMutationFlags = honourDoneMutationFlags;
|
|
51
51
|
|
|
52
52
|
this.#ports = ports;
|
|
53
|
-
|
|
54
|
-
this.#ports.forEach((port) => MessagePortPlus.upgradeInPlace(port, { autoStart: options.autoStart, postAwaitsOpen: options.postAwaitsOpen }));
|
|
53
|
+
this.#ports.forEach((port) => MessagePortPlus.upgradeInPlace(port));
|
|
55
54
|
|
|
56
55
|
if (_isTypeObject(this.#data) && this.#live) {
|
|
57
56
|
if (typeof eventID !== 'string') {
|
package/src/MessagePortPlus.js
CHANGED
|
@@ -29,10 +29,18 @@ const portPlusProps = [
|
|
|
29
29
|
|
|
30
30
|
export class MessagePortPlus extends MessagePortPlusMixin(EventTarget) {
|
|
31
31
|
|
|
32
|
-
constructor(options = {}) {
|
|
32
|
+
constructor({ handshake = 0, postAwaitsOpen = false, ...options } = {}) {
|
|
33
|
+
if (typeof handshake !== 'number') {
|
|
34
|
+
throw new Error('handshake must be a number');
|
|
35
|
+
}
|
|
36
|
+
if (handshake < 0 || handshake > 2) {
|
|
37
|
+
throw new Error('handshake must be between 0 and 2');
|
|
38
|
+
}
|
|
39
|
+
|
|
33
40
|
super();
|
|
41
|
+
|
|
34
42
|
const portPlusMeta = _wq(this, 'meta');
|
|
35
|
-
portPlusMeta.set('options', options);
|
|
43
|
+
portPlusMeta.set('options', { handshake, postAwaitsOpen, ...options });
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
static [Symbol.hasInstance](instance) {
|
|
@@ -47,11 +55,18 @@ export class MessagePortPlus extends MessagePortPlusMixin(EventTarget) {
|
|
|
47
55
|
export function MessagePortPlusMixin(superClass) {
|
|
48
56
|
return class extends superClass {
|
|
49
57
|
|
|
50
|
-
static upgradeInPlace(port,
|
|
58
|
+
static upgradeInPlace(port, { handshake = 0, postAwaitsOpen = false } = {}) {
|
|
51
59
|
if (port instanceof MessagePortPlus) {
|
|
52
60
|
return port;
|
|
53
61
|
}
|
|
54
62
|
|
|
63
|
+
if (typeof handshake !== 'number') {
|
|
64
|
+
throw new Error('handshake must be a number');
|
|
65
|
+
}
|
|
66
|
+
if (handshake < 0 || handshake > 2) {
|
|
67
|
+
throw new Error('handshake must be between 0 and 2');
|
|
68
|
+
}
|
|
69
|
+
|
|
55
70
|
const proto = this.prototype;
|
|
56
71
|
|
|
57
72
|
for (const prop of portPlusMethods.concat('_autoStart')) {
|
|
@@ -71,9 +86,12 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
71
86
|
}
|
|
72
87
|
|
|
73
88
|
const portPlusMeta = _wq(port, 'meta');
|
|
74
|
-
portPlusMeta.set('options',
|
|
89
|
+
portPlusMeta.set('options', { handshake, postAwaitsOpen });
|
|
75
90
|
|
|
76
91
|
this.upgradeEvents(port);
|
|
92
|
+
|
|
93
|
+
if (handshake === 0) port.start();
|
|
94
|
+
|
|
77
95
|
return port;
|
|
78
96
|
}
|
|
79
97
|
|
|
@@ -115,28 +133,34 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
115
133
|
|
|
116
134
|
if (e.data.ping === 'connect'
|
|
117
135
|
&& typeof e.data?.['.wq']?.eventID === 'string'
|
|
118
|
-
&& (!(port instanceof WebSocket) ||
|
|
136
|
+
&& (!(port instanceof WebSocket) || options.handshake)) {
|
|
119
137
|
// This is a special ping from a MessagePort or BroadcastChannel instance
|
|
120
138
|
// that helps us simulate an "open" event
|
|
121
|
-
// If
|
|
139
|
+
// If options.handshake !== 0, WebSockets too
|
|
122
140
|
|
|
123
|
-
|
|
141
|
+
const nowOpen = options.handshake === 0
|
|
142
|
+
|| portPlusMeta.get('start.called');
|
|
143
|
+
|
|
144
|
+
const reply = { isOpen: nowOpen };
|
|
124
145
|
|
|
125
146
|
if (port instanceof BroadcastChannel) {
|
|
126
147
|
if (options.clientServerMode === 'server'
|
|
127
148
|
&& typeof e.data.id === 'string') {
|
|
128
149
|
portPlusMeta.get('clients').add(e.data.id);
|
|
129
|
-
reply = 'server';
|
|
150
|
+
reply.id = 'server';
|
|
130
151
|
} else if (e.data.id === 'server'
|
|
131
152
|
&& portPlusMeta.has('client_id')) {
|
|
132
|
-
reply = portPlusMeta.get('client_id');
|
|
153
|
+
reply.id = portPlusMeta.get('client_id');
|
|
133
154
|
}
|
|
134
155
|
}
|
|
135
156
|
|
|
136
157
|
e.ports?.forEach((p) => p.postMessage(reply));
|
|
137
158
|
|
|
138
|
-
|
|
139
|
-
|
|
159
|
+
if (nowOpen) {
|
|
160
|
+
portPlusMeta.set('remote.open.called', true);
|
|
161
|
+
portPlus.start();
|
|
162
|
+
}
|
|
163
|
+
|
|
140
164
|
return;
|
|
141
165
|
}
|
|
142
166
|
|
|
@@ -195,46 +219,19 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
195
219
|
portPlus.dispatchEvent(eventPlus);
|
|
196
220
|
};
|
|
197
221
|
|
|
198
|
-
// ------------- OPEN
|
|
199
|
-
|
|
200
|
-
const openHandler = (e) => {
|
|
201
|
-
// Native "open" event fired by WebSocket
|
|
202
|
-
if (port instanceof WebSocket
|
|
203
|
-
&& options.naturalOpen
|
|
204
|
-
&& !(e instanceof MessageEventPlus)) {
|
|
205
|
-
portPlusMeta.set('remote.start.called', true);
|
|
206
|
-
portPlus.start();
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
// ------------- CLOSE
|
|
211
|
-
|
|
212
|
-
const closeHandler = (e) => {
|
|
213
|
-
// Native "close" events fired by MessagePort and WebSocket
|
|
214
|
-
if ((port instanceof WebSocket || port instanceof MessagePort)
|
|
215
|
-
&& !(e instanceof MessageEventPlus)) {
|
|
216
|
-
portPlusMeta.set('remote.close.called', true);
|
|
217
|
-
portPlus.close();
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
|
|
221
222
|
rawPortMeta.set('internal_call', true);
|
|
222
223
|
port.addEventListener('message', messageHandler);
|
|
223
224
|
port.addEventListener('error', messageHandler);
|
|
224
|
-
port.addEventListener('open', openHandler);
|
|
225
|
-
port.addEventListener('close', closeHandler);
|
|
226
225
|
rawPortMeta.delete('internal_call');
|
|
227
226
|
|
|
228
|
-
rawPortMeta.set('events+', true);
|
|
229
|
-
|
|
230
227
|
garbageCollection.add(() => {
|
|
231
228
|
port.removeEventListener('message', messageHandler);
|
|
232
229
|
port.removeEventListener('error', messageHandler);
|
|
233
|
-
port.removeEventListener('open', openHandler);
|
|
234
|
-
port.removeEventListener('close', closeHandler);
|
|
235
230
|
|
|
236
231
|
rawPortMeta.set('events+', false);
|
|
237
232
|
});
|
|
233
|
+
|
|
234
|
+
rawPortMeta.set('events+', true);
|
|
238
235
|
}
|
|
239
236
|
|
|
240
237
|
get options() { return { ..._options(this) }; }
|
|
@@ -282,11 +279,9 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
282
279
|
}
|
|
283
280
|
|
|
284
281
|
set onmessage(v) {
|
|
285
|
-
// Auto-start?
|
|
286
|
-
this._autoStart();
|
|
287
|
-
|
|
288
282
|
if (typeof super.onmessage !== 'undefined') {
|
|
289
283
|
super.onmessage = v;
|
|
284
|
+
this._autoStart();
|
|
290
285
|
return;
|
|
291
286
|
}
|
|
292
287
|
|
|
@@ -296,18 +291,17 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
296
291
|
|
|
297
292
|
if (Object.getOwnPropertyDescriptor(this, '_onmessage')?.set) {
|
|
298
293
|
this._onmessage = v;
|
|
294
|
+
this._autoStart();
|
|
299
295
|
return;
|
|
300
296
|
}
|
|
301
297
|
|
|
302
298
|
if (this._onmessage) this.removeEventListener('message', this._onmessage);
|
|
303
299
|
this.addEventListener('message', v);
|
|
304
300
|
this._onmessage = v;
|
|
301
|
+
this._autoStart();
|
|
305
302
|
}
|
|
306
303
|
|
|
307
304
|
addEventListener(...args) {
|
|
308
|
-
// Auto-start?
|
|
309
|
-
this._autoStart();
|
|
310
|
-
|
|
311
305
|
// Add to registry
|
|
312
306
|
const garbageCollection = getGarbageCollection.call(this);
|
|
313
307
|
garbageCollection.add(() => {
|
|
@@ -317,9 +311,11 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
317
311
|
});
|
|
318
312
|
|
|
319
313
|
// Execute addEventListener()
|
|
320
|
-
|
|
314
|
+
const returnValue = this._addEventListener
|
|
321
315
|
? this._addEventListener(...args)
|
|
322
316
|
: super.addEventListener(...args);
|
|
317
|
+
this._autoStart();
|
|
318
|
+
return returnValue;
|
|
323
319
|
}
|
|
324
320
|
|
|
325
321
|
dispatchEvent(event) {
|
|
@@ -334,7 +330,6 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
334
330
|
}
|
|
335
331
|
|
|
336
332
|
postMessage(message, transferOrOptions = {}) {
|
|
337
|
-
// Auto-start?
|
|
338
333
|
this._autoStart();
|
|
339
334
|
|
|
340
335
|
// Update readyState
|
|
@@ -455,21 +450,21 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
455
450
|
};
|
|
456
451
|
}
|
|
457
452
|
|
|
458
|
-
channel(channelSpec, resolveMessage = null) {
|
|
453
|
+
channel(channelSpec, resolveMessage = null, { handshake = 0, postAwaitsOpen = false } = {}) {
|
|
459
454
|
const channel = new MessageChannel;
|
|
460
455
|
|
|
461
|
-
MessagePortPlus.upgradeInPlace(channel.port1, {
|
|
462
|
-
MessagePortPlus.upgradeInPlace(channel.port2, {
|
|
456
|
+
MessagePortPlus.upgradeInPlace(channel.port1, { handshake, postAwaitsOpen });
|
|
457
|
+
MessagePortPlus.upgradeInPlace(channel.port2, { handshake, postAwaitsOpen });
|
|
463
458
|
|
|
464
459
|
const garbageCollection = getGarbageCollection.call(this);
|
|
465
|
-
garbageCollection.add(this.relay({ channel: channelSpec, to: channel.
|
|
460
|
+
garbageCollection.add(this.relay({ channel: channelSpec, to: channel.port2, bidirectional: true, resolveMessage }));
|
|
466
461
|
|
|
467
|
-
channel.
|
|
462
|
+
channel.port2.start();
|
|
468
463
|
this.readyStateChange('close').then(() => {
|
|
469
|
-
channel.
|
|
464
|
+
channel.port2.close();
|
|
470
465
|
});
|
|
471
466
|
|
|
472
|
-
return channel.
|
|
467
|
+
return channel.port1;
|
|
473
468
|
}
|
|
474
469
|
|
|
475
470
|
projectMutations({ from, to, ...options }) {
|
|
@@ -509,7 +504,7 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
509
504
|
const portPlusMeta = _meta(this);
|
|
510
505
|
const options = _options(this);
|
|
511
506
|
if (!portPlusMeta.get('internal_call')
|
|
512
|
-
&& options.
|
|
507
|
+
&& options.handshake === 1) {
|
|
513
508
|
this.start();
|
|
514
509
|
}
|
|
515
510
|
}
|
|
@@ -518,30 +513,29 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
518
513
|
const readyStateInternals = getReadyStateInternals.call(this);
|
|
519
514
|
if (readyStateInternals.open.state) return;
|
|
520
515
|
|
|
521
|
-
let messageChannel;
|
|
522
|
-
|
|
523
|
-
const readyStateOpen = () => {
|
|
524
|
-
if (readyStateInternals.open.state) return;
|
|
525
|
-
readyStateInternals.open.state = true;
|
|
526
|
-
readyStateInternals.open.resolve(this);
|
|
527
|
-
|
|
528
|
-
const openEvent = new MessageEventPlus(null, { type: 'open' });
|
|
529
|
-
this._dispatchEvent
|
|
530
|
-
? this._dispatchEvent(openEvent)
|
|
531
|
-
: super.dispatchEvent(openEvent);
|
|
532
|
-
|
|
533
|
-
messageChannel?.port1.close();
|
|
534
|
-
messageChannel?.port2.close();
|
|
535
|
-
};
|
|
536
|
-
|
|
537
516
|
const portPlusMeta = _meta(this);
|
|
538
517
|
const options = _options(this);
|
|
539
518
|
|
|
540
|
-
|
|
541
|
-
|
|
519
|
+
const readyStateOpen = (nowOpen) => {
|
|
520
|
+
if (nowOpen) {
|
|
521
|
+
readyStateInternals.open.state = true;
|
|
522
|
+
readyStateInternals.open.resolve(this);
|
|
523
|
+
}
|
|
524
|
+
const handshakeChannel = portPlusMeta.get('handshake_channel');
|
|
525
|
+
setTimeout(() => {
|
|
526
|
+
handshakeChannel?.port1.close();
|
|
527
|
+
handshakeChannel?.port2.close();
|
|
528
|
+
portPlusMeta.delete('handshake_channel');
|
|
529
|
+
}, 100);
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
// A peer ping triggered us to open
|
|
533
|
+
if (portPlusMeta.get('remote.open.called')) {
|
|
534
|
+
readyStateOpen(true);
|
|
542
535
|
return;
|
|
543
536
|
}
|
|
544
537
|
|
|
538
|
+
// Start was explicitly called
|
|
545
539
|
if (portPlusMeta.get('start.called')) return;
|
|
546
540
|
portPlusMeta.set('start.called', true);
|
|
547
541
|
|
|
@@ -549,16 +543,26 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
549
543
|
? this._start()
|
|
550
544
|
: super.start?.();
|
|
551
545
|
|
|
552
|
-
|
|
546
|
+
// No handshake?
|
|
547
|
+
if (options.handshake === 0) {
|
|
548
|
+
readyStateOpen(true);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const handshakeChannel = new MessageChannel;
|
|
553
|
+
portPlusMeta.set('handshake_channel', handshakeChannel);
|
|
553
554
|
|
|
554
|
-
|
|
555
|
+
handshakeChannel.port1.onmessage = (e) => {
|
|
555
556
|
if (this instanceof BroadcastChannel
|
|
556
557
|
&& options.clientServerMode === 'server'
|
|
557
|
-
&& typeof e.data === 'string') {
|
|
558
|
+
&& typeof e.data?.id === 'string') {
|
|
558
559
|
// Register clients that replied
|
|
559
|
-
portPlusMeta.get('clients').add(e.data);
|
|
560
|
+
portPlusMeta.get('clients').add(e.data.id);
|
|
560
561
|
}
|
|
561
|
-
|
|
562
|
+
if (typeof e.data?.isOpen) {
|
|
563
|
+
// This peer is ready to start messaging
|
|
564
|
+
readyStateOpen(true);
|
|
565
|
+
} else readyStateOpen(false);
|
|
562
566
|
};
|
|
563
567
|
|
|
564
568
|
const { wqOptions } = preProcessPostMessage.call(this);
|
|
@@ -567,8 +571,8 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
567
571
|
const pingData = { ['.wq']: wqOptions, ping: 'connect', id };
|
|
568
572
|
|
|
569
573
|
this._postMessage
|
|
570
|
-
? this._postMessage(pingData, { transfer: [
|
|
571
|
-
: super.postMessage(pingData, { transfer: [
|
|
574
|
+
? this._postMessage(pingData, { transfer: [handshakeChannel.port2] })
|
|
575
|
+
: super.postMessage(pingData, { transfer: [handshakeChannel.port2] });
|
|
572
576
|
}
|
|
573
577
|
|
|
574
578
|
close(...args) {
|
|
@@ -580,7 +584,8 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
580
584
|
const portPlusMeta = _meta(this);
|
|
581
585
|
const options = _options(this);
|
|
582
586
|
|
|
583
|
-
if (
|
|
587
|
+
if (options.handshake > 0
|
|
588
|
+
&& !portPlusMeta.get('remote.close.called')
|
|
584
589
|
&& (this instanceof BroadcastChannel || this instanceof MessagePort)) {
|
|
585
590
|
|
|
586
591
|
const { wqOptions } = preProcessPostMessage.call(this);
|
|
@@ -604,11 +609,6 @@ export function MessagePortPlusMixin(superClass) {
|
|
|
604
609
|
|
|
605
610
|
readyStateInternals.close.resolve(this);
|
|
606
611
|
|
|
607
|
-
const openEvent = new MessageEventPlus(null, { type: 'close' });
|
|
608
|
-
this._dispatchEvent
|
|
609
|
-
? this._dispatchEvent(openEvent)
|
|
610
|
-
: super.dispatchEvent(openEvent);
|
|
611
|
-
|
|
612
612
|
garbageCollect.call(this);
|
|
613
613
|
}
|
|
614
614
|
};
|
|
@@ -832,6 +832,7 @@ export function publishMutations(message, eventID, { signal, withArrayMethodDesc
|
|
|
832
832
|
if (mutationsDone) dispose.abort();
|
|
833
833
|
};
|
|
834
834
|
|
|
835
|
+
|
|
835
836
|
const dispose = Observer.observe(message, Observer.subtree(), mutationHandler, { signal, withArrayMethodDescriptors });
|
|
836
837
|
const garbageCollection = getGarbageCollection.call(this);
|
|
837
838
|
garbageCollection.add(dispose);
|
package/src/StarPort.js
CHANGED
|
@@ -8,13 +8,16 @@ import {
|
|
|
8
8
|
export class StarPort extends MessagePortPlus {
|
|
9
9
|
|
|
10
10
|
#ports = new Set;
|
|
11
|
+
#startCalled = false;
|
|
12
|
+
#closeCalled = false;
|
|
11
13
|
|
|
12
14
|
get length() { return this.#ports.size; }
|
|
13
15
|
|
|
14
16
|
[Symbol.iterator]() { return this.#ports[Symbol.iterator](); }
|
|
15
17
|
|
|
16
|
-
constructor({
|
|
17
|
-
super({
|
|
18
|
+
constructor({ handshake = 0, postAwaitsOpen = false, autoClose = false } = {}) {
|
|
19
|
+
super({ handshake, postAwaitsOpen, autoClose });
|
|
20
|
+
if (handshake === 0) this.start();
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
addPort(portPlus, { enableBubbling = true } = {}) {
|
|
@@ -24,7 +27,7 @@ export class StarPort extends MessagePortPlus {
|
|
|
24
27
|
|
|
25
28
|
const readyStateInternals = getReadyStateInternals.call(this);
|
|
26
29
|
|
|
27
|
-
if (readyStateInternals.close.state) {
|
|
30
|
+
if (this.#closeCalled || readyStateInternals.close.state) {
|
|
28
31
|
const starPortName = this.constructor.name;
|
|
29
32
|
throw new Error(`Cannot add port to ${starPortName}. ${starPortName} is closed.`);
|
|
30
33
|
}
|
|
@@ -41,8 +44,17 @@ export class StarPort extends MessagePortPlus {
|
|
|
41
44
|
portPlusMeta.set('parentNode', this); // @ORDER: 2
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
if (this.options.handshake) {
|
|
48
|
+
portPlus.readyStateChange('open').then(() => {
|
|
49
|
+
readyStateInternals.open.state = true;
|
|
50
|
+
readyStateInternals.open.resolve(this);
|
|
51
|
+
});
|
|
52
|
+
portPlus.readyStateChange('close').then(() => cleanup());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (this.#startCalled || readyStateInternals.open.state) {
|
|
56
|
+
portPlus.start();
|
|
57
|
+
}
|
|
46
58
|
|
|
47
59
|
const cleanup = () => {
|
|
48
60
|
if (!this.#ports.has(portPlus)) return;
|
|
@@ -56,7 +68,8 @@ export class StarPort extends MessagePortPlus {
|
|
|
56
68
|
|
|
57
69
|
if (this.#ports.size === 0
|
|
58
70
|
&& _options(this).autoClose) {
|
|
59
|
-
|
|
71
|
+
readyStateInternals.close.state = true;
|
|
72
|
+
readyStateInternals.close.resolve(this);
|
|
60
73
|
}
|
|
61
74
|
};
|
|
62
75
|
|
|
@@ -78,33 +91,33 @@ export class StarPort extends MessagePortPlus {
|
|
|
78
91
|
}
|
|
79
92
|
}
|
|
80
93
|
|
|
81
|
-
_autoStart() { } // Must be present to do nothing
|
|
82
|
-
|
|
83
94
|
start() {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (readyStateInternals.open.state) return;
|
|
87
|
-
readyStateInternals.open.state = true;
|
|
95
|
+
if (this.#startCalled) return;
|
|
96
|
+
this.#startCalled = true;
|
|
88
97
|
|
|
89
|
-
|
|
98
|
+
for (const portPlus of this.#ports) {
|
|
99
|
+
portPlus.start();
|
|
100
|
+
}
|
|
90
101
|
|
|
91
|
-
|
|
92
|
-
|
|
102
|
+
if (!this.options.handshake) {
|
|
103
|
+
const readyStateInternals = getReadyStateInternals.call(this);
|
|
104
|
+
readyStateInternals.open.state = true;
|
|
105
|
+
readyStateInternals.open.resolve(this);
|
|
106
|
+
}
|
|
93
107
|
}
|
|
94
108
|
|
|
95
109
|
close(...args) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (readyStateInternals.close.state) return;
|
|
99
|
-
readyStateInternals.close.state = true;
|
|
110
|
+
if (this.#closeCalled) return;
|
|
111
|
+
this.#closeCalled = true;
|
|
100
112
|
|
|
101
113
|
for (const portPlus of this.#ports) {
|
|
102
|
-
portPlus.close
|
|
114
|
+
portPlus.close(...args);
|
|
103
115
|
}
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
if (!this.options.handshake) {
|
|
118
|
+
const readyStateInternals = getReadyStateInternals.call(this);
|
|
119
|
+
readyStateInternals.close.state = true;
|
|
120
|
+
readyStateInternals.close.resolve(this);
|
|
121
|
+
}
|
|
109
122
|
}
|
|
110
123
|
}
|
package/src/WebSocketPort.js
CHANGED
|
@@ -9,30 +9,42 @@ export class WebSocketPort extends MessagePortPlusMockPortsMixin(EventTarget) {
|
|
|
9
9
|
#ws;
|
|
10
10
|
#wsReady;
|
|
11
11
|
|
|
12
|
-
constructor(ws, {
|
|
12
|
+
constructor(ws, { handshake = 0, postAwaitsOpen = false } = {}) {
|
|
13
13
|
super();
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
|
|
15
|
+
if (typeof handshake !== 'number') {
|
|
16
|
+
throw new Error('handshake must be a number');
|
|
17
|
+
}
|
|
18
|
+
if (handshake < 0 || handshake > 2) {
|
|
19
|
+
throw new Error('handshake must be between 0 and 2');
|
|
20
|
+
}
|
|
21
|
+
|
|
16
22
|
const portPlusMeta = _meta(this);
|
|
17
|
-
portPlusMeta.set('options', {
|
|
23
|
+
portPlusMeta.set('options', { handshake, postAwaitsOpen });
|
|
18
24
|
// Must come before upgradeEvents()
|
|
19
25
|
|
|
26
|
+
this.#ws = typeof ws === 'string' ? new WebSocket(ws) : ws;
|
|
27
|
+
|
|
20
28
|
this.constructor/* IMPORTANT */.upgradeEvents(this.#ws, this);
|
|
21
29
|
|
|
22
|
-
if (naturalOpen
|
|
23
|
-
&& autoStart
|
|
24
|
-
&& this.#ws.readyState === WebSocket.OPEN) {
|
|
25
|
-
this.start();
|
|
26
|
-
}
|
|
27
30
|
this.#wsReady = new Promise((resolve) => {
|
|
28
31
|
if (this.#ws.readyState === WebSocket.OPEN) {
|
|
29
32
|
resolve();
|
|
30
33
|
} else {
|
|
31
|
-
this.#ws.addEventListener('open', resolve);
|
|
34
|
+
this.#ws.addEventListener('open', () => resolve(), { once: true });
|
|
32
35
|
}
|
|
33
36
|
});
|
|
37
|
+
|
|
38
|
+
if (handshake === 0) {
|
|
39
|
+
this.#wsReady.then(() => this.start());
|
|
40
|
+
}
|
|
41
|
+
|
|
34
42
|
if (this.#ws.readyState === WebSocket.CLOSED) {
|
|
35
|
-
try { this.close(); } catch(e) {}
|
|
43
|
+
try { this.close(); } catch (e) { }
|
|
44
|
+
} else {
|
|
45
|
+
this.#ws.addEventListener('close', () => {
|
|
46
|
+
try { this.close(); } catch (e) { }
|
|
47
|
+
}, { once: true });
|
|
36
48
|
}
|
|
37
49
|
}
|
|
38
50
|
|
|
@@ -45,7 +57,7 @@ export class WebSocketPort extends MessagePortPlusMockPortsMixin(EventTarget) {
|
|
|
45
57
|
Object.defineProperty(event, 'data', { value: data, configurable: true });
|
|
46
58
|
return super._hydrateMessage(portPlus, event);
|
|
47
59
|
}
|
|
48
|
-
} catch (e) {}
|
|
60
|
+
} catch (e) { }
|
|
49
61
|
return event;
|
|
50
62
|
}
|
|
51
63
|
|