@openfin/remote-adapter 47.100.27 → 47.100.29
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/out/remote-adapter.js +275 -118
- package/package.json +2 -2
package/out/remote-adapter.js
CHANGED
|
@@ -10200,19 +10200,39 @@ let ChannelError$1 = class ChannelError extends Error {
|
|
|
10200
10200
|
}
|
|
10201
10201
|
};
|
|
10202
10202
|
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10203
|
+
/**
|
|
10204
|
+
* Tracks live channel clients by their current endpoint id and routes runtime lifecycle events to them.
|
|
10205
|
+
*/
|
|
10206
|
+
class ChannelClientStore {
|
|
10207
|
+
// The provider for a channel has gone away: every client on that channel is disconnected.
|
|
10208
|
+
static handleProviderDisconnect(eventPayload) {
|
|
10209
|
+
[...ChannelClientStore.clients.values()].forEach((client) => {
|
|
10210
|
+
if (client.providerIdentity.channelId === eventPayload.channelId) {
|
|
10211
|
+
client[teardown](true, false);
|
|
10212
|
+
}
|
|
10213
|
+
});
|
|
10214
|
+
}
|
|
10215
|
+
// Old providers omit endpoint ids, so a new connection silently replaces the previous client on the channel.
|
|
10216
|
+
static handleEndpointDisconnect(endpointId) {
|
|
10217
|
+
ChannelClientStore.clients.get(endpointId)?.[teardown](false, false);
|
|
10218
|
+
}
|
|
10219
|
+
}
|
|
10220
|
+
ChannelClientStore.clients = new Map();
|
|
10221
|
+
|
|
10208
10222
|
var __classPrivateFieldSet$h = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
10209
10223
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
10210
10224
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
10211
10225
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10212
10226
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
10213
10227
|
};
|
|
10214
|
-
var
|
|
10215
|
-
|
|
10228
|
+
var __classPrivateFieldGet$i = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
10229
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10230
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10231
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
10232
|
+
};
|
|
10233
|
+
var _ChannelClient_currentConnection, _ChannelClient_state, _ChannelClient_wire, _ChannelClient_reestablish, _ChannelClient_unsubscribeBFCache, _ChannelClient_disconnectListener, _ChannelClient_reconnectListener, _ChannelClient_releaseConnection, _ChannelClient_attach, _ChannelClient_sendDisconnectToRuntime, _ChannelClient_reconnect;
|
|
10234
|
+
// Key for ChannelClient's internal teardown function. Prevents the need to expose internal functions.
|
|
10235
|
+
const teardown = Symbol('teardown');
|
|
10216
10236
|
/**
|
|
10217
10237
|
* Instance created to enable use of a channel as a client. Allows for communication with the
|
|
10218
10238
|
* {@link ChannelProvider ChannelProvider} by invoking an action on the
|
|
@@ -10241,50 +10261,135 @@ class ChannelClient extends ChannelBase {
|
|
|
10241
10261
|
/**
|
|
10242
10262
|
* @internal
|
|
10243
10263
|
*/
|
|
10244
|
-
|
|
10245
|
-
|
|
10246
|
-
|
|
10247
|
-
|
|
10248
|
-
|
|
10264
|
+
constructor(config) {
|
|
10265
|
+
super();
|
|
10266
|
+
_ChannelClient_currentConnection.set(this, void 0);
|
|
10267
|
+
_ChannelClient_state.set(this, { status: 'connected' });
|
|
10268
|
+
_ChannelClient_wire.set(this, void 0);
|
|
10269
|
+
_ChannelClient_reestablish.set(this, void 0);
|
|
10270
|
+
_ChannelClient_unsubscribeBFCache.set(this, void 0);
|
|
10271
|
+
_ChannelClient_disconnectListener.set(this, void 0);
|
|
10272
|
+
_ChannelClient_reconnectListener.set(this, void 0);
|
|
10273
|
+
// needs to be bound;
|
|
10274
|
+
this.processAction = (action, payload, senderIdentity) => super.processAction(action, payload, senderIdentity);
|
|
10275
|
+
_ChannelClient_releaseConnection.set(this, async (connection, notifyRuntime) => {
|
|
10276
|
+
connection.strategy.close().catch(() => undefined);
|
|
10277
|
+
if (notifyRuntime) {
|
|
10278
|
+
await __classPrivateFieldGet$i(this, _ChannelClient_sendDisconnectToRuntime, "f").call(this, connection);
|
|
10279
|
+
}
|
|
10280
|
+
});
|
|
10281
|
+
_ChannelClient_attach.set(this, (instance) => {
|
|
10282
|
+
ChannelClientStore.clients.set(instance.routingInfo.endpointId, this);
|
|
10283
|
+
instance.strategy.receive(this.processAction);
|
|
10284
|
+
instance.strategy.onEndpointDisconnect(instance.routingInfo.channelId, () => {
|
|
10285
|
+
// Only a drop of the live endpoint disconnects. During a self-heal the endpoint is already being replaced
|
|
10286
|
+
// and the handshake decides the outcome; after it, closing the replaced strategy (RTC/combined fire this on
|
|
10287
|
+
// close) must not tear down the client now live on a fresh endpoint.
|
|
10288
|
+
if (__classPrivateFieldGet$i(this, _ChannelClient_currentConnection, "f") === instance && __classPrivateFieldGet$i(this, _ChannelClient_state, "f").status === 'connected') {
|
|
10289
|
+
this[teardown](true).catch((error) => {
|
|
10290
|
+
// eslint-disable-next-line no-console
|
|
10291
|
+
console.warn(`Failed to notify the runtime that channel '${instance.routingInfo.channelName}' endpoint ${instance.routingInfo.endpointId} disconnected.`, error);
|
|
10292
|
+
});
|
|
10293
|
+
}
|
|
10294
|
+
});
|
|
10295
|
+
});
|
|
10296
|
+
_ChannelClient_sendDisconnectToRuntime.set(this, async ({ routingInfo }) => {
|
|
10297
|
+
const { channelName, uuid, name, endpointId } = routingInfo;
|
|
10298
|
+
await __classPrivateFieldGet$i(this, _ChannelClient_wire, "f").sendAction('disconnect-from-channel', { channelName, uuid, name, endpointId });
|
|
10299
|
+
});
|
|
10300
|
+
// Re-handshakes (new endpointId) and swaps in the fresh endpoint. Client-side registrations and middleware live
|
|
10301
|
+
// on `this` (ChannelBase), so they carry over. Overlapping BF-Cache restores share one in-flight handshake.
|
|
10302
|
+
_ChannelClient_reconnect.set(this, async () => {
|
|
10303
|
+
if (__classPrivateFieldGet$i(this, _ChannelClient_state, "f").status === 'connected') {
|
|
10304
|
+
const performReconnect = async () => {
|
|
10305
|
+
let next;
|
|
10306
|
+
try {
|
|
10307
|
+
next = await __classPrivateFieldGet$i(this, _ChannelClient_reestablish, "f").call(this);
|
|
10308
|
+
}
|
|
10309
|
+
catch (error) {
|
|
10310
|
+
// No automatic retry: recovery is up to the onDisconnection handler.
|
|
10311
|
+
// eslint-disable-next-line no-console
|
|
10312
|
+
console.warn(`Channel '${__classPrivateFieldGet$i(this, _ChannelClient_currentConnection, "f").routingInfo.channelName}' failed to self-heal after BF-Cache restoration; disconnecting.`, error);
|
|
10313
|
+
await this[teardown](true).catch((disconnectError) => {
|
|
10314
|
+
// eslint-disable-next-line no-console
|
|
10315
|
+
console.warn(`Failed to notify the runtime that channel '${__classPrivateFieldGet$i(this, _ChannelClient_currentConnection, "f").routingInfo.channelName}' disconnected.`, disconnectError);
|
|
10316
|
+
});
|
|
10317
|
+
return;
|
|
10318
|
+
}
|
|
10319
|
+
// A disconnect() or provider disconnect may have landed while the handshake was in flight; if so,
|
|
10320
|
+
// tear down the freshly established endpoint instead of resurrecting a closed client.
|
|
10321
|
+
if (__classPrivateFieldGet$i(this, _ChannelClient_state, "f").status !== 'reconnecting') {
|
|
10322
|
+
__classPrivateFieldGet$i(this, _ChannelClient_releaseConnection, "f").call(this, next, true).catch(() => undefined);
|
|
10323
|
+
return;
|
|
10324
|
+
}
|
|
10325
|
+
const previous = __classPrivateFieldGet$i(this, _ChannelClient_currentConnection, "f");
|
|
10326
|
+
__classPrivateFieldSet$h(this, _ChannelClient_currentConnection, next, "f");
|
|
10327
|
+
__classPrivateFieldGet$i(this, _ChannelClient_attach, "f").call(this, next);
|
|
10328
|
+
__classPrivateFieldSet$h(this, _ChannelClient_state, { status: 'connected' }, "f");
|
|
10329
|
+
// A throwing listener must not abort the reconnect.
|
|
10330
|
+
try {
|
|
10331
|
+
__classPrivateFieldGet$i(this, _ChannelClient_reconnectListener, "f")?.call(this, {
|
|
10332
|
+
providerIdentity: this.providerIdentity,
|
|
10333
|
+
previousEndpointId: previous.routingInfo.endpointId,
|
|
10334
|
+
endpointId: next.routingInfo.endpointId
|
|
10335
|
+
});
|
|
10336
|
+
}
|
|
10337
|
+
catch (error) {
|
|
10338
|
+
// eslint-disable-next-line no-console
|
|
10339
|
+
console.warn(`An unexpected error occurred in a Channel Client Reconnection handler for channel ${next.routingInfo.channelName}`, error);
|
|
10340
|
+
}
|
|
10341
|
+
// The old endpoint is typically already gone (navigation); closing is best-effort cleanup.
|
|
10342
|
+
__classPrivateFieldGet$i(this, _ChannelClient_releaseConnection, "f").call(this, previous, false).catch(() => undefined);
|
|
10343
|
+
};
|
|
10344
|
+
// The endpoint is being replaced: against old providers the handshake supersedes it by id, which must
|
|
10345
|
+
// not close the reconnecting client.
|
|
10346
|
+
ChannelClientStore.clients.delete(__classPrivateFieldGet$i(this, _ChannelClient_currentConnection, "f").routingInfo.endpointId);
|
|
10347
|
+
const reconnectPromise = performReconnect();
|
|
10348
|
+
__classPrivateFieldSet$h(this, _ChannelClient_state, { status: 'reconnecting', waitForReconnection: () => reconnectPromise }, "f");
|
|
10349
|
+
}
|
|
10350
|
+
if (__classPrivateFieldGet$i(this, _ChannelClient_state, "f").status === 'reconnecting') {
|
|
10351
|
+
await __classPrivateFieldGet$i(this, _ChannelClient_state, "f").waitForReconnection();
|
|
10352
|
+
}
|
|
10353
|
+
});
|
|
10354
|
+
__classPrivateFieldSet$h(this, _ChannelClient_currentConnection, config.initialConnection, "f");
|
|
10355
|
+
__classPrivateFieldSet$h(this, _ChannelClient_wire, config.wire, "f");
|
|
10356
|
+
__classPrivateFieldSet$h(this, _ChannelClient_reestablish, config.reestablish, "f");
|
|
10357
|
+
__classPrivateFieldSet$h(this, _ChannelClient_unsubscribeBFCache, __classPrivateFieldGet$i(this, _ChannelClient_wire, "f").environment.onBFCacheRestore(__classPrivateFieldGet$i(this, _ChannelClient_reconnect, "f")), "f");
|
|
10358
|
+
__classPrivateFieldGet$i(this, _ChannelClient_attach, "f").call(this, config.initialConnection);
|
|
10249
10359
|
}
|
|
10250
10360
|
/**
|
|
10251
10361
|
* @internal
|
|
10252
|
-
*
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
|
|
10256
|
-
|
|
10257
|
-
|
|
10258
|
-
|
|
10362
|
+
* Closes the client. `notifyRuntime` sends `disconnect-from-channel` for the current endpoint; `emitEvent` then
|
|
10363
|
+
* fires the onDisconnection listener, even if notifying the runtime failed.
|
|
10364
|
+
*/
|
|
10365
|
+
async [(_ChannelClient_currentConnection = new WeakMap(), _ChannelClient_state = new WeakMap(), _ChannelClient_wire = new WeakMap(), _ChannelClient_reestablish = new WeakMap(), _ChannelClient_unsubscribeBFCache = new WeakMap(), _ChannelClient_disconnectListener = new WeakMap(), _ChannelClient_reconnectListener = new WeakMap(), _ChannelClient_releaseConnection = new WeakMap(), _ChannelClient_attach = new WeakMap(), _ChannelClient_sendDisconnectToRuntime = new WeakMap(), _ChannelClient_reconnect = new WeakMap(), teardown)](emitEvent = false, notifyRuntime = true) {
|
|
10366
|
+
if (__classPrivateFieldGet$i(this, _ChannelClient_state, "f").status !== 'closed') {
|
|
10367
|
+
const identity = this.providerIdentity;
|
|
10368
|
+
const connection = __classPrivateFieldGet$i(this, _ChannelClient_currentConnection, "f");
|
|
10369
|
+
__classPrivateFieldSet$h(this, _ChannelClient_state, { status: 'closed' }, "f");
|
|
10370
|
+
__classPrivateFieldGet$i(this, _ChannelClient_unsubscribeBFCache, "f").call(this);
|
|
10371
|
+
ChannelClientStore.clients.delete(connection.routingInfo.endpointId);
|
|
10372
|
+
try {
|
|
10373
|
+
await __classPrivateFieldGet$i(this, _ChannelClient_releaseConnection, "f").call(this, connection, notifyRuntime);
|
|
10374
|
+
}
|
|
10375
|
+
finally {
|
|
10376
|
+
if (emitEvent) {
|
|
10377
|
+
try {
|
|
10378
|
+
__classPrivateFieldGet$i(this, _ChannelClient_disconnectListener, "f")?.call(this, identity);
|
|
10379
|
+
}
|
|
10380
|
+
catch (error) {
|
|
10381
|
+
// eslint-disable-next-line no-console
|
|
10382
|
+
console.warn(`An unexpected error occurred in a Channel Client Disconnection handler for channel ${identity.channelName}`, error);
|
|
10383
|
+
}
|
|
10384
|
+
}
|
|
10259
10385
|
}
|
|
10260
10386
|
}
|
|
10261
10387
|
}
|
|
10262
|
-
/**
|
|
10263
|
-
* @internal
|
|
10264
|
-
*/
|
|
10265
|
-
constructor(routingInfo, close, strategy) {
|
|
10266
|
-
super();
|
|
10267
|
-
_ChannelClient_protectedObj.set(this, void 0);
|
|
10268
|
-
_ChannelClient_strategy.set(this, void 0);
|
|
10269
|
-
// needs to be bound;
|
|
10270
|
-
this.processAction = (action, payload, senderIdentity) => super.processAction(action, payload, senderIdentity);
|
|
10271
|
-
_ChannelClient_close.set(this, () => {
|
|
10272
|
-
channelClientsByEndpointId.delete(this.endpointId);
|
|
10273
|
-
__classPrivateFieldGet$i(this, _ChannelClient_strategy, "f").close();
|
|
10274
|
-
});
|
|
10275
|
-
__classPrivateFieldSet$h(this, _ChannelClient_protectedObj, new ProtectedItems(routingInfo, close), "f");
|
|
10276
|
-
this.disconnectListener = () => undefined;
|
|
10277
|
-
this.endpointId = routingInfo.endpointId;
|
|
10278
|
-
__classPrivateFieldSet$h(this, _ChannelClient_strategy, strategy, "f");
|
|
10279
|
-
channelClientsByEndpointId.set(this.endpointId, this);
|
|
10280
|
-
strategy.receive(this.processAction);
|
|
10281
|
-
}
|
|
10282
10388
|
/**
|
|
10283
10389
|
* a read-only provider identity
|
|
10284
10390
|
*/
|
|
10285
10391
|
get providerIdentity() {
|
|
10286
|
-
|
|
10287
|
-
return protectedObj.providerIdentity;
|
|
10392
|
+
return { ...__classPrivateFieldGet$i(this, _ChannelClient_currentConnection, "f").routingInfo };
|
|
10288
10393
|
}
|
|
10289
10394
|
/**
|
|
10290
10395
|
* Dispatch the given action to the channel provider. Returns a promise that resolves with the response from
|
|
@@ -10312,17 +10417,22 @@ class ChannelClient extends ChannelBase {
|
|
|
10312
10417
|
* ```
|
|
10313
10418
|
*/
|
|
10314
10419
|
async dispatch(action, payload) {
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
throw new ChannelError$1(e, action, payload, callSites);
|
|
10319
|
-
});
|
|
10420
|
+
// App pageshow handlers run alongside the bfcache restore; sending now would go out on the frozen endpoint.
|
|
10421
|
+
if (__classPrivateFieldGet$i(this, _ChannelClient_state, "f").status === 'reconnecting') {
|
|
10422
|
+
await __classPrivateFieldGet$i(this, _ChannelClient_state, "f").waitForReconnection();
|
|
10320
10423
|
}
|
|
10321
|
-
|
|
10424
|
+
const connection = __classPrivateFieldGet$i(this, _ChannelClient_currentConnection, "f");
|
|
10425
|
+
if (!connection.strategy.isEndpointConnected(this.providerIdentity.channelId)) {
|
|
10426
|
+
throw new Error('The client you are trying to dispatch from is disconnected from the target provider.');
|
|
10427
|
+
}
|
|
10428
|
+
const callSites = RuntimeError.getCallSite();
|
|
10429
|
+
return connection.strategy.send(this.providerIdentity.channelId, action, payload).catch((e) => {
|
|
10430
|
+
throw new ChannelError$1(e, action, payload, callSites);
|
|
10431
|
+
});
|
|
10322
10432
|
}
|
|
10323
10433
|
/**
|
|
10324
|
-
* Register a listener that is called
|
|
10325
|
-
*
|
|
10434
|
+
* Register a listener that is called when this client loses its channel: the provider disconnects, the
|
|
10435
|
+
* endpoint drops, or a self-heal fails. It is passed the provider identity.
|
|
10326
10436
|
*
|
|
10327
10437
|
* @param listener
|
|
10328
10438
|
*
|
|
@@ -10339,17 +10449,46 @@ class ChannelClient extends ChannelBase {
|
|
|
10339
10449
|
* ```
|
|
10340
10450
|
*/
|
|
10341
10451
|
onDisconnection(listener) {
|
|
10342
|
-
this
|
|
10343
|
-
|
|
10344
|
-
|
|
10345
|
-
|
|
10346
|
-
|
|
10347
|
-
|
|
10348
|
-
|
|
10349
|
-
|
|
10350
|
-
|
|
10351
|
-
|
|
10352
|
-
|
|
10452
|
+
__classPrivateFieldSet$h(this, _ChannelClient_disconnectListener, listener, "f");
|
|
10453
|
+
}
|
|
10454
|
+
/**
|
|
10455
|
+
* Register a listener that is called each time this client transparently self-heals its connection to the
|
|
10456
|
+
* provider.
|
|
10457
|
+
*
|
|
10458
|
+
* @remarks
|
|
10459
|
+
* A channel client's underlying endpoint is torn down while its document sits in the back/forward cache
|
|
10460
|
+
* (bfcache). If the back/forward cache is supported and the document is restored from it, the client
|
|
10461
|
+
* automatically re-handshakes with the provider and swaps in a fresh endpoint; all of this client's
|
|
10462
|
+
* `register`/middleware handlers are preserved, so no re-registration is required.
|
|
10463
|
+
*
|
|
10464
|
+
* A restore is not guaranteed: Chromium may evict a cached document at any time, in which case navigating
|
|
10465
|
+
* back reloads the page and a new client must connect.
|
|
10466
|
+
*
|
|
10467
|
+
* This listener fires once per successful reconnect, after the new endpoint is live, and can fire multiple
|
|
10468
|
+
* times over the client's lifetime. It is triggered when the document is restored from the back/forward
|
|
10469
|
+
* cache (a bfcache `pageshow`). It does not fire for the initial connection, nor after
|
|
10470
|
+
* {@link ChannelClient#disconnect disconnect}. {@link ChannelClient#onDisconnection onDisconnection} fires
|
|
10471
|
+
* when the provider or endpoint goes away.
|
|
10472
|
+
*
|
|
10473
|
+
* The info provides the reconnected {@link OpenFin.ProviderIdentity provider identity} along with
|
|
10474
|
+
* the previous and new endpoint ids.
|
|
10475
|
+
*
|
|
10476
|
+
* @param listener
|
|
10477
|
+
*
|
|
10478
|
+
* @example
|
|
10479
|
+
*
|
|
10480
|
+
* ```js
|
|
10481
|
+
* (async () => {
|
|
10482
|
+
* const client = await fin.InterApplicationBus.Channel.connect('channelName');
|
|
10483
|
+
*
|
|
10484
|
+
* client.onReconnection(({ providerIdentity, previousEndpointId, endpointId }) => {
|
|
10485
|
+
* console.log(`Reconnected to ${providerIdentity.channelName}: ${previousEndpointId} -> ${endpointId}`);
|
|
10486
|
+
* });
|
|
10487
|
+
* })();
|
|
10488
|
+
* ```
|
|
10489
|
+
*/
|
|
10490
|
+
onReconnection(listener) {
|
|
10491
|
+
__classPrivateFieldSet$h(this, _ChannelClient_reconnectListener, listener, "f");
|
|
10353
10492
|
}
|
|
10354
10493
|
/**
|
|
10355
10494
|
* Disconnects the client from the channel.
|
|
@@ -10365,28 +10504,16 @@ class ChannelClient extends ChannelBase {
|
|
|
10365
10504
|
* ```
|
|
10366
10505
|
*/
|
|
10367
10506
|
async disconnect() {
|
|
10368
|
-
await this
|
|
10369
|
-
__classPrivateFieldGet$i(this, _ChannelClient_close, "f").call(this);
|
|
10370
|
-
}
|
|
10371
|
-
async sendDisconnectAction() {
|
|
10372
|
-
const protectedObj = __classPrivateFieldGet$i(this, _ChannelClient_protectedObj, "f");
|
|
10373
|
-
await protectedObj.close();
|
|
10507
|
+
await this[teardown](false);
|
|
10374
10508
|
}
|
|
10375
10509
|
/**
|
|
10376
10510
|
* @internal
|
|
10377
|
-
*
|
|
10511
|
+
* Notify the runtime that the current endpoint has disconnected.
|
|
10378
10512
|
*/
|
|
10379
|
-
|
|
10380
|
-
|
|
10381
|
-
await wire.sendAction('disconnect-from-channel', {
|
|
10382
|
-
channelName,
|
|
10383
|
-
uuid,
|
|
10384
|
-
name,
|
|
10385
|
-
endpointId
|
|
10386
|
-
});
|
|
10513
|
+
async sendDisconnectAction() {
|
|
10514
|
+
await this.disconnect();
|
|
10387
10515
|
}
|
|
10388
10516
|
}
|
|
10389
|
-
_ChannelClient_protectedObj = new WeakMap(), _ChannelClient_strategy = new WeakMap(), _ChannelClient_close = new WeakMap();
|
|
10390
10517
|
|
|
10391
10518
|
function exhaustiveCheck(value, allowed) {
|
|
10392
10519
|
throw new Error(`Unsupported value: ${value}${allowed ? `\n Supported values are: ${allowed.join('')}` : ''}`);
|
|
@@ -11296,7 +11423,7 @@ class MessageReceiver extends Base {
|
|
|
11296
11423
|
const endpointIdFromPreviousConnection = this.latestEndpointIdByChannelId.get(channelId);
|
|
11297
11424
|
if (endpointIdFromPreviousConnection) {
|
|
11298
11425
|
// Not convinced by this way of doing things, but pushing up for now.
|
|
11299
|
-
|
|
11426
|
+
ChannelClientStore.handleEndpointDisconnect(endpointIdFromPreviousConnection);
|
|
11300
11427
|
// eslint-disable-next-line no-console
|
|
11301
11428
|
console.warn('You have created a second connection to an older provider. First connection has been removed from the clientMap');
|
|
11302
11429
|
// eslint-disable-next-line no-console
|
|
@@ -11671,7 +11798,7 @@ var __classPrivateFieldGet$c = (undefined && undefined.__classPrivateFieldGet) |
|
|
|
11671
11798
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11672
11799
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11673
11800
|
};
|
|
11674
|
-
var _Channel_connectionManager, _Channel_internalEmitter, _Channel_readyForProvider, _Channel_readyToConnect;
|
|
11801
|
+
var _Channel_connectionManager, _Channel_internalEmitter, _Channel_readyForProvider, _Channel_readyToConnect, _Channel_establishConnection;
|
|
11675
11802
|
function retryDelay(count) {
|
|
11676
11803
|
const interval = 500; // base delay
|
|
11677
11804
|
const steps = 10; // How many retries to do before incrementing the delay
|
|
@@ -11721,13 +11848,33 @@ class Channel extends EmitterBase {
|
|
|
11721
11848
|
await Promise.all([
|
|
11722
11849
|
__classPrivateFieldGet$c(this, _Channel_readyForProvider, "f").getValue(),
|
|
11723
11850
|
this.on('disconnected', (eventPayload) => {
|
|
11724
|
-
|
|
11851
|
+
ChannelClientStore.handleProviderDisconnect(eventPayload);
|
|
11725
11852
|
}),
|
|
11726
11853
|
this.on('connected', (...args) => {
|
|
11727
11854
|
__classPrivateFieldGet$c(this, _Channel_internalEmitter, "f").emit('connected', ...args);
|
|
11728
11855
|
})
|
|
11729
11856
|
]).catch(() => new Error('error setting up channel connection listeners'));
|
|
11730
11857
|
}));
|
|
11858
|
+
// Runs the client handshake (offer -> connect -> strategy). Re-runnable so a ChannelClient can reconnect
|
|
11859
|
+
// with a fresh endpointId; offers are single-use (esp. RTC) so a new offer is created each call.
|
|
11860
|
+
_Channel_establishConnection.set(this, async (channelName, opts, connectionUrl) => {
|
|
11861
|
+
const { offer, rtc: rtcPacket } = await __classPrivateFieldGet$c(this, _Channel_connectionManager, "f").createClientOffer(opts);
|
|
11862
|
+
// getInfo() can hang during a bfcache restore, so reconnects reuse the URL resolved on the first connect;
|
|
11863
|
+
// it cannot change within a client's lifetime.
|
|
11864
|
+
let targetUrl = connectionUrl;
|
|
11865
|
+
if (targetUrl === undefined && (this.fin.me.isFrame || this.fin.me.isView || this.fin.me.isWindow)) {
|
|
11866
|
+
targetUrl = (await this.fin.me.getInfo()).url;
|
|
11867
|
+
}
|
|
11868
|
+
const connectPayload = {
|
|
11869
|
+
channelName,
|
|
11870
|
+
...opts,
|
|
11871
|
+
offer,
|
|
11872
|
+
connectionUrl: targetUrl
|
|
11873
|
+
};
|
|
11874
|
+
const routingInfo = await this.safeConnect(channelName, opts.wait, connectPayload);
|
|
11875
|
+
const strategy = await __classPrivateFieldGet$c(this, _Channel_connectionManager, "f").createClientStrategy(rtcPacket, routingInfo);
|
|
11876
|
+
return { routingInfo, strategy, connectionUrl: targetUrl };
|
|
11877
|
+
});
|
|
11731
11878
|
__classPrivateFieldSet$b(this, _Channel_connectionManager, new ConnectionManager(wire), "f");
|
|
11732
11879
|
}
|
|
11733
11880
|
/**
|
|
@@ -11899,35 +12046,14 @@ class Channel extends EmitterBase {
|
|
|
11899
12046
|
throw new Error('Please provide a channelName string to connect to a channel.');
|
|
11900
12047
|
}
|
|
11901
12048
|
const opts = { wait: true, ...this.wire.environment.getDefaultChannelOptions().connect, ...options };
|
|
11902
|
-
const
|
|
11903
|
-
|
|
11904
|
-
|
|
11905
|
-
|
|
11906
|
-
|
|
11907
|
-
|
|
11908
|
-
channelName,
|
|
11909
|
-
...opts,
|
|
11910
|
-
offer,
|
|
11911
|
-
connectionUrl
|
|
11912
|
-
};
|
|
11913
|
-
const routingInfo = await this.safeConnect(channelName, opts.wait, connectPayload);
|
|
11914
|
-
const strategy = await __classPrivateFieldGet$c(this, _Channel_connectionManager, "f").createClientStrategy(rtcPacket, routingInfo);
|
|
11915
|
-
const channel = new ChannelClient(routingInfo, () => ChannelClient.wireClose(this.wire, routingInfo, routingInfo.endpointId), strategy);
|
|
11916
|
-
// It is the client's responsibility to handle endpoint disconnection to the provider.
|
|
11917
|
-
// If the endpoint dies, the client will force a disconnection through the core.
|
|
11918
|
-
// The provider does not care about endpoint disconnection.
|
|
11919
|
-
strategy.onEndpointDisconnect(routingInfo.channelId, async () => {
|
|
11920
|
-
try {
|
|
11921
|
-
await channel.sendDisconnectAction();
|
|
11922
|
-
}
|
|
11923
|
-
catch (error) {
|
|
11924
|
-
console.warn(`Something went wrong during disconnect for client with uuid: ${routingInfo.uuid} / name: ${routingInfo.name} / endpointId: ${routingInfo.endpointId}.`);
|
|
11925
|
-
}
|
|
11926
|
-
finally {
|
|
11927
|
-
ChannelClient.handleProviderDisconnect(routingInfo);
|
|
11928
|
-
}
|
|
12049
|
+
const initialConnection = await __classPrivateFieldGet$c(this, _Channel_establishConnection, "f").call(this, channelName, opts);
|
|
12050
|
+
// Never wait on a self-heal: a provider missing at restore has gone away, which is a disconnection. A provider
|
|
12051
|
+
// created later under the same name is a new instance without this client's provider-side state.
|
|
12052
|
+
return new ChannelClient({
|
|
12053
|
+
initialConnection,
|
|
12054
|
+
wire: this.wire,
|
|
12055
|
+
reestablish: () => __classPrivateFieldGet$c(this, _Channel_establishConnection, "f").call(this, channelName, { ...opts, wait: false }, initialConnection.connectionUrl)
|
|
11929
12056
|
});
|
|
11930
|
-
return channel;
|
|
11931
12057
|
}
|
|
11932
12058
|
/**
|
|
11933
12059
|
* Create a new channel.
|
|
@@ -11984,7 +12110,7 @@ class Channel extends EmitterBase {
|
|
|
11984
12110
|
return __classPrivateFieldGet$c(this, _Channel_connectionManager, "f").createProvider(options, providerIdentity);
|
|
11985
12111
|
}
|
|
11986
12112
|
}
|
|
11987
|
-
_Channel_connectionManager = new WeakMap(), _Channel_internalEmitter = new WeakMap(), _Channel_readyForProvider = new WeakMap(), _Channel_readyToConnect = new WeakMap();
|
|
12113
|
+
_Channel_connectionManager = new WeakMap(), _Channel_internalEmitter = new WeakMap(), _Channel_readyForProvider = new WeakMap(), _Channel_readyToConnect = new WeakMap(), _Channel_establishConnection = new WeakMap();
|
|
11988
12114
|
|
|
11989
12115
|
/**
|
|
11990
12116
|
* Entry point for the OpenFin `InterApplicationBus` API (`fin.InterApplicationBus`).
|
|
@@ -12018,11 +12144,27 @@ class InterApplicationBus extends Base {
|
|
|
12018
12144
|
subscriberRemoved: 'subscriber-removed'
|
|
12019
12145
|
};
|
|
12020
12146
|
this.refCounter = new RefCounter();
|
|
12147
|
+
/**
|
|
12148
|
+
* One entry per subscription the runtime knows about, keyed by the same subscription key the
|
|
12149
|
+
* emitter and the ref counter use. Listeners sharing a key share a single entry.
|
|
12150
|
+
*/
|
|
12151
|
+
this.activeSubscriptions = new Map();
|
|
12021
12152
|
this.Channel = new Channel(wire);
|
|
12022
12153
|
this.emitter = new events.EventEmitter();
|
|
12023
12154
|
wire.registerMessageHandler(this.onmessage.bind(this));
|
|
12024
12155
|
this.on = this.emitter.on.bind(this.emitter);
|
|
12025
12156
|
this.removeAllListeners = this.emitter.removeAllListeners.bind(this.emitter);
|
|
12157
|
+
wire.environment.onBFCacheRestore(() => {
|
|
12158
|
+
Array.from(this.activeSubscriptions.values()).forEach(async (subscription) => {
|
|
12159
|
+
try {
|
|
12160
|
+
await this.wire.sendAction('subscribe', subscription);
|
|
12161
|
+
}
|
|
12162
|
+
catch (error) {
|
|
12163
|
+
// eslint-disable-next-line no-console
|
|
12164
|
+
console.error('Failed to restore InterApplicationBus subscription after bfcache restore', error);
|
|
12165
|
+
}
|
|
12166
|
+
});
|
|
12167
|
+
});
|
|
12026
12168
|
}
|
|
12027
12169
|
/**
|
|
12028
12170
|
* Publishes a message to all applications running on OpenFin Runtime that
|
|
@@ -12074,30 +12216,39 @@ class InterApplicationBus extends Base {
|
|
|
12074
12216
|
* Subscribes to messages from the specified application on the specified topic.
|
|
12075
12217
|
* @param source This object is described in the Identity in the typedef
|
|
12076
12218
|
* @param topic The topic on which the message is sent
|
|
12077
|
-
* @param listener A function that is called when a message has
|
|
12078
|
-
*
|
|
12219
|
+
* @param listener A function that is called when a message has been received. It is passed
|
|
12220
|
+
* two arguments: the message, and the identity (`{ uuid, name }`) of the sender.
|
|
12079
12221
|
* The message can be either a primitive data type (string, number, or boolean) or
|
|
12080
12222
|
* composite data type (object, array) that is composed of other primitive or composite
|
|
12081
12223
|
* data types
|
|
12082
12224
|
*
|
|
12225
|
+
* @remarks This differs from the legacy `fin.desktop.InterApplicationBus.subscribe` API,
|
|
12226
|
+
* which passes `(message, uuid, name)` as separate arguments.
|
|
12227
|
+
*
|
|
12083
12228
|
* @example
|
|
12084
12229
|
* ```js
|
|
12085
12230
|
* // subscribe to a specified application
|
|
12086
|
-
* fin.InterApplicationBus.subscribe(fin.me, 'topic',
|
|
12231
|
+
* fin.InterApplicationBus.subscribe(fin.me, 'topic', (message, sender) => {
|
|
12232
|
+
* console.log(`Received from ${sender.uuid}/${sender.name}:`, message);
|
|
12233
|
+
* }).then(() => console.log('Subscribed to the specified application')).catch(err => console.log(err));
|
|
12087
12234
|
*
|
|
12088
12235
|
* // subscribe to wildcard
|
|
12089
12236
|
* fin.InterApplicationBus.subscribe({ uuid: '*' }, 'topic', sub_msg => console.log(sub_msg)).then(() => console.log('Subscribed to *')).catch(err => console.log(err));
|
|
12090
12237
|
* ```
|
|
12091
12238
|
*/
|
|
12092
12239
|
subscribe(source, topic, listener) {
|
|
12093
|
-
const
|
|
12240
|
+
const sourceWindowName = source.name || '*';
|
|
12241
|
+
const subKey = this.createSubscriptionKey(source.uuid, sourceWindowName, topic);
|
|
12242
|
+
const subscription = {
|
|
12243
|
+
sourceUuid: source.uuid,
|
|
12244
|
+
sourceWindowName,
|
|
12245
|
+
topic,
|
|
12246
|
+
destinationWindowName: this.me.name
|
|
12247
|
+
};
|
|
12094
12248
|
const sendSubscription = async () => {
|
|
12095
|
-
await
|
|
12096
|
-
|
|
12097
|
-
|
|
12098
|
-
topic,
|
|
12099
|
-
destinationWindowName: this.me.name
|
|
12100
|
-
});
|
|
12249
|
+
// Journaled before the await so a concurrent unsubscribe can find it.
|
|
12250
|
+
this.activeSubscriptions.set(subKey, subscription);
|
|
12251
|
+
await this.wire.sendAction('subscribe', subscription);
|
|
12101
12252
|
};
|
|
12102
12253
|
const alreadySubscribed = () => {
|
|
12103
12254
|
return Promise.resolve();
|
|
@@ -12133,6 +12284,9 @@ class InterApplicationBus extends Base {
|
|
|
12133
12284
|
const sourceWindowName = source.name || '*';
|
|
12134
12285
|
const subKey = this.createSubscriptionKey(source.uuid, sourceWindowName, topic);
|
|
12135
12286
|
const sendUnsubscription = async () => {
|
|
12287
|
+
// Dropped before the await so that a restoration landing while this unsubscribe is
|
|
12288
|
+
// still in flight does not replay the subscription being torn down.
|
|
12289
|
+
this.activeSubscriptions.delete(subKey);
|
|
12136
12290
|
await this.wire.sendAction('unsubscribe', {
|
|
12137
12291
|
sourceUuid: source.uuid,
|
|
12138
12292
|
sourceWindowName,
|
|
@@ -12141,6 +12295,9 @@ class InterApplicationBus extends Base {
|
|
|
12141
12295
|
});
|
|
12142
12296
|
};
|
|
12143
12297
|
const dontSendUnsubscription = () => {
|
|
12298
|
+
// TODO(CORE-2749): never settles - the executor evaluates `r` instead of calling it,
|
|
12299
|
+
// so awaiting a non-final unsubscribe hangs the caller. Should be `Promise.resolve()`,
|
|
12300
|
+
// but that changes long-standing behavior, so it is tracked separately from CORE-2740.
|
|
12144
12301
|
return new Promise((r) => r).then(() => undefined);
|
|
12145
12302
|
};
|
|
12146
12303
|
this.emitter.removeListener(subKey, listener);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfin/remote-adapter",
|
|
3
|
-
"version": "47.100.
|
|
3
|
+
"version": "47.100.29",
|
|
4
4
|
"description": "Establish intermachine runtime connections using webRTC.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"private": false,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"es-toolkit": "^1.39.3",
|
|
18
18
|
"tslib": "2.8.1",
|
|
19
|
-
"@openfin/core": "47.100.
|
|
19
|
+
"@openfin/core": "47.100.29"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"prebuild": "rimraf ./out",
|