@dynamic-labs-wallet/browser-wallet-client 0.0.338 → 0.0.340
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/index.cjs +69 -11
- package/index.esm.js +69 -11
- package/package.json +2 -2
- package/src/client/iframeManager/IframeManager.d.ts.map +1 -1
package/index.cjs
CHANGED
|
@@ -238,6 +238,18 @@ const setupMessageTransportBridge = (messageTransport$1, iframe, iframeOrigin)=>
|
|
|
238
238
|
};
|
|
239
239
|
|
|
240
240
|
const FRAME_ANCESTORS_QUERY_PARAM = 'frameAncestors';
|
|
241
|
+
/**
|
|
242
|
+
* Whether the given iframe element is mounted and accessible.
|
|
243
|
+
*
|
|
244
|
+
* - contentWindow becomes null once the iframe is removed from the DOM.
|
|
245
|
+
* - isConnected returns false when the element has been detached. Some test
|
|
246
|
+
* environments leave it undefined, which we treat as alive — falling back
|
|
247
|
+
* to "absence === alive" matches the production behavior on real
|
|
248
|
+
* HTMLIFrameElement.
|
|
249
|
+
*/ const isIframeAlive = (iframe)=>{
|
|
250
|
+
var _iframe_isConnected;
|
|
251
|
+
return !!(iframe == null ? void 0 : iframe.contentWindow) && ((_iframe_isConnected = iframe.isConnected) != null ? _iframe_isConnected : true);
|
|
252
|
+
};
|
|
241
253
|
/**
|
|
242
254
|
* Builds the iframe message transport with the recovery + block decorators.
|
|
243
255
|
*
|
|
@@ -334,18 +346,39 @@ class IframeManager {
|
|
|
334
346
|
* goes 5s without an ack — typically because the iframe was torn down by a
|
|
335
347
|
* relogin or RN modal unmount and the host still holds a stale reference.
|
|
336
348
|
*/ async recoverIframe(transport) {
|
|
337
|
-
|
|
338
|
-
//
|
|
339
|
-
//
|
|
340
|
-
|
|
349
|
+
// If sharedIframe is still alive (contentWindow + connected), the request
|
|
350
|
+
// channel's 5s timeout fired for a *non-iframe-death* reason — slow
|
|
351
|
+
// server, overloaded MPC ceremony, etc. Rebuilding the iframe in that
|
|
352
|
+
// case actively breaks things: it removes a healthy iframe out from
|
|
353
|
+
// under in-flight operations and amplifies retries when the next
|
|
354
|
+
// message also times out → endless cascade.
|
|
355
|
+
//
|
|
356
|
+
// Just unblock the transport (the request channel's own retry will
|
|
357
|
+
// re-send the message on the same live iframe) and bail out. Only the
|
|
358
|
+
// real dead-iframe case below falls through to the rebuild.
|
|
359
|
+
if (isIframeAlive(IframeManager.sharedIframe)) {
|
|
360
|
+
this.logger.info('(recoverIframe) Iframe still alive — request-channel timeout, skipping rebuild');
|
|
361
|
+
this.iframe = IframeManager.sharedIframe;
|
|
362
|
+
transport.unblock();
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
341
365
|
// Detach listeners attached to the dead iframe.
|
|
342
366
|
this.cleanupBridge == null ? void 0 : this.cleanupBridge.call(this);
|
|
343
367
|
this.cleanupBridge = null;
|
|
344
|
-
(_IframeManager_sharedIframe = IframeManager.sharedIframe) == null ? void 0 : _IframeManager_sharedIframe.remove();
|
|
345
|
-
IframeManager.sharedIframe = null;
|
|
346
|
-
IframeManager.iframeLoadPromise = null;
|
|
347
368
|
this.iframe = null;
|
|
369
|
+
// Defer the DOM rebuild + concurrency control to loadIframe(): the first
|
|
370
|
+
// chain to land here will fall through to the remount branch (sharedIframe
|
|
371
|
+
// is dead, iframeLoadPromise is null), set iframeLoadPromise, and start
|
|
372
|
+
// the mount. Subsequent chains' loadIframe() calls during this window see
|
|
373
|
+
// iframeLoadPromise set and await the same load — concurrent rebuilds
|
|
374
|
+
// collapse for free, no extra static needed.
|
|
375
|
+
//
|
|
376
|
+
// The transport, iframeMessageHandler, and iframeRequestChannel are
|
|
377
|
+
// intentionally kept — they're tied to the request channel's in-flight
|
|
378
|
+
// retry that we want to flush after rebuild.
|
|
379
|
+
this.logger.info('(recoverIframe) Rebuilding shared iframe');
|
|
348
380
|
await this.loadIframe();
|
|
381
|
+
this.iframe = IframeManager.sharedIframe;
|
|
349
382
|
if (!this.iframe) {
|
|
350
383
|
throw new Error('Failed to mount fresh iframe during recovery');
|
|
351
384
|
}
|
|
@@ -442,8 +475,14 @@ class IframeManager {
|
|
|
442
475
|
IframeManager.iframeLoadTimeout = Math.min(IframeManager.iframeLoadTimeout * 2, 60000);
|
|
443
476
|
}
|
|
444
477
|
async loadIframe() {
|
|
445
|
-
//
|
|
446
|
-
|
|
478
|
+
var // sharedIframe is dead (or never existed) and no load is in flight.
|
|
479
|
+
// Clear the stale corpse so createIframeLoadPromise mounts a fresh one.
|
|
480
|
+
_IframeManager_sharedIframe;
|
|
481
|
+
// If sharedIframe is still alive (contentWindow + connected), reuse it.
|
|
482
|
+
// The alive check (not just `if sharedIframe`) is what lets recoverIframe
|
|
483
|
+
// simply call loadIframe again on a dead iframe: we fall through to the
|
|
484
|
+
// remount branch below instead of adopting the corpse.
|
|
485
|
+
if (isIframeAlive(IframeManager.sharedIframe)) {
|
|
447
486
|
this.assignExistingIframe();
|
|
448
487
|
return Promise.resolve();
|
|
449
488
|
}
|
|
@@ -453,8 +492,27 @@ class IframeManager {
|
|
|
453
492
|
this.assignExistingIframe();
|
|
454
493
|
});
|
|
455
494
|
}
|
|
456
|
-
IframeManager.
|
|
457
|
-
|
|
495
|
+
(_IframeManager_sharedIframe = IframeManager.sharedIframe) == null ? void 0 : _IframeManager_sharedIframe.remove();
|
|
496
|
+
IframeManager.sharedIframe = null;
|
|
497
|
+
const loadPromise = IframeManager.iframeLoadPromise = this.createIframeLoadPromise();
|
|
498
|
+
// Clear iframeLoadPromise once the load settles so the "in flight" branch
|
|
499
|
+
// above only fires while a load is actually pending. Otherwise it would
|
|
500
|
+
// keep returning a resolved promise pointing at the (potentially later
|
|
501
|
+
// dead) iframe, and the next caller would adopt a corpse without ever
|
|
502
|
+
// taking the remount branch.
|
|
503
|
+
//
|
|
504
|
+
// The trailing .catch swallows the rejection that finally re-throws —
|
|
505
|
+
// the original error still propagates to the caller via the returned
|
|
506
|
+
// loadPromise; this side chain just keeps unhandled rejections out of
|
|
507
|
+
// jest test reports / process listeners.
|
|
508
|
+
loadPromise.finally(()=>{
|
|
509
|
+
if (IframeManager.iframeLoadPromise === loadPromise) {
|
|
510
|
+
IframeManager.iframeLoadPromise = null;
|
|
511
|
+
}
|
|
512
|
+
}).catch(()=>{
|
|
513
|
+
// Original rejection is delivered through the returned loadPromise.
|
|
514
|
+
});
|
|
515
|
+
return loadPromise;
|
|
458
516
|
}
|
|
459
517
|
assignExistingIframe() {
|
|
460
518
|
this.iframe = IframeManager.sharedIframe;
|
package/index.esm.js
CHANGED
|
@@ -237,6 +237,18 @@ const setupMessageTransportBridge = (messageTransport, iframe, iframeOrigin)=>{
|
|
|
237
237
|
};
|
|
238
238
|
|
|
239
239
|
const FRAME_ANCESTORS_QUERY_PARAM = 'frameAncestors';
|
|
240
|
+
/**
|
|
241
|
+
* Whether the given iframe element is mounted and accessible.
|
|
242
|
+
*
|
|
243
|
+
* - contentWindow becomes null once the iframe is removed from the DOM.
|
|
244
|
+
* - isConnected returns false when the element has been detached. Some test
|
|
245
|
+
* environments leave it undefined, which we treat as alive — falling back
|
|
246
|
+
* to "absence === alive" matches the production behavior on real
|
|
247
|
+
* HTMLIFrameElement.
|
|
248
|
+
*/ const isIframeAlive = (iframe)=>{
|
|
249
|
+
var _iframe_isConnected;
|
|
250
|
+
return !!(iframe == null ? void 0 : iframe.contentWindow) && ((_iframe_isConnected = iframe.isConnected) != null ? _iframe_isConnected : true);
|
|
251
|
+
};
|
|
240
252
|
/**
|
|
241
253
|
* Builds the iframe message transport with the recovery + block decorators.
|
|
242
254
|
*
|
|
@@ -333,18 +345,39 @@ class IframeManager {
|
|
|
333
345
|
* goes 5s without an ack — typically because the iframe was torn down by a
|
|
334
346
|
* relogin or RN modal unmount and the host still holds a stale reference.
|
|
335
347
|
*/ async recoverIframe(transport) {
|
|
336
|
-
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
|
|
348
|
+
// If sharedIframe is still alive (contentWindow + connected), the request
|
|
349
|
+
// channel's 5s timeout fired for a *non-iframe-death* reason — slow
|
|
350
|
+
// server, overloaded MPC ceremony, etc. Rebuilding the iframe in that
|
|
351
|
+
// case actively breaks things: it removes a healthy iframe out from
|
|
352
|
+
// under in-flight operations and amplifies retries when the next
|
|
353
|
+
// message also times out → endless cascade.
|
|
354
|
+
//
|
|
355
|
+
// Just unblock the transport (the request channel's own retry will
|
|
356
|
+
// re-send the message on the same live iframe) and bail out. Only the
|
|
357
|
+
// real dead-iframe case below falls through to the rebuild.
|
|
358
|
+
if (isIframeAlive(IframeManager.sharedIframe)) {
|
|
359
|
+
this.logger.info('(recoverIframe) Iframe still alive — request-channel timeout, skipping rebuild');
|
|
360
|
+
this.iframe = IframeManager.sharedIframe;
|
|
361
|
+
transport.unblock();
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
340
364
|
// Detach listeners attached to the dead iframe.
|
|
341
365
|
this.cleanupBridge == null ? void 0 : this.cleanupBridge.call(this);
|
|
342
366
|
this.cleanupBridge = null;
|
|
343
|
-
(_IframeManager_sharedIframe = IframeManager.sharedIframe) == null ? void 0 : _IframeManager_sharedIframe.remove();
|
|
344
|
-
IframeManager.sharedIframe = null;
|
|
345
|
-
IframeManager.iframeLoadPromise = null;
|
|
346
367
|
this.iframe = null;
|
|
368
|
+
// Defer the DOM rebuild + concurrency control to loadIframe(): the first
|
|
369
|
+
// chain to land here will fall through to the remount branch (sharedIframe
|
|
370
|
+
// is dead, iframeLoadPromise is null), set iframeLoadPromise, and start
|
|
371
|
+
// the mount. Subsequent chains' loadIframe() calls during this window see
|
|
372
|
+
// iframeLoadPromise set and await the same load — concurrent rebuilds
|
|
373
|
+
// collapse for free, no extra static needed.
|
|
374
|
+
//
|
|
375
|
+
// The transport, iframeMessageHandler, and iframeRequestChannel are
|
|
376
|
+
// intentionally kept — they're tied to the request channel's in-flight
|
|
377
|
+
// retry that we want to flush after rebuild.
|
|
378
|
+
this.logger.info('(recoverIframe) Rebuilding shared iframe');
|
|
347
379
|
await this.loadIframe();
|
|
380
|
+
this.iframe = IframeManager.sharedIframe;
|
|
348
381
|
if (!this.iframe) {
|
|
349
382
|
throw new Error('Failed to mount fresh iframe during recovery');
|
|
350
383
|
}
|
|
@@ -441,8 +474,14 @@ class IframeManager {
|
|
|
441
474
|
IframeManager.iframeLoadTimeout = Math.min(IframeManager.iframeLoadTimeout * 2, 60000);
|
|
442
475
|
}
|
|
443
476
|
async loadIframe() {
|
|
444
|
-
//
|
|
445
|
-
|
|
477
|
+
var // sharedIframe is dead (or never existed) and no load is in flight.
|
|
478
|
+
// Clear the stale corpse so createIframeLoadPromise mounts a fresh one.
|
|
479
|
+
_IframeManager_sharedIframe;
|
|
480
|
+
// If sharedIframe is still alive (contentWindow + connected), reuse it.
|
|
481
|
+
// The alive check (not just `if sharedIframe`) is what lets recoverIframe
|
|
482
|
+
// simply call loadIframe again on a dead iframe: we fall through to the
|
|
483
|
+
// remount branch below instead of adopting the corpse.
|
|
484
|
+
if (isIframeAlive(IframeManager.sharedIframe)) {
|
|
446
485
|
this.assignExistingIframe();
|
|
447
486
|
return Promise.resolve();
|
|
448
487
|
}
|
|
@@ -452,8 +491,27 @@ class IframeManager {
|
|
|
452
491
|
this.assignExistingIframe();
|
|
453
492
|
});
|
|
454
493
|
}
|
|
455
|
-
IframeManager.
|
|
456
|
-
|
|
494
|
+
(_IframeManager_sharedIframe = IframeManager.sharedIframe) == null ? void 0 : _IframeManager_sharedIframe.remove();
|
|
495
|
+
IframeManager.sharedIframe = null;
|
|
496
|
+
const loadPromise = IframeManager.iframeLoadPromise = this.createIframeLoadPromise();
|
|
497
|
+
// Clear iframeLoadPromise once the load settles so the "in flight" branch
|
|
498
|
+
// above only fires while a load is actually pending. Otherwise it would
|
|
499
|
+
// keep returning a resolved promise pointing at the (potentially later
|
|
500
|
+
// dead) iframe, and the next caller would adopt a corpse without ever
|
|
501
|
+
// taking the remount branch.
|
|
502
|
+
//
|
|
503
|
+
// The trailing .catch swallows the rejection that finally re-throws —
|
|
504
|
+
// the original error still propagates to the caller via the returned
|
|
505
|
+
// loadPromise; this side chain just keeps unhandled rejections out of
|
|
506
|
+
// jest test reports / process listeners.
|
|
507
|
+
loadPromise.finally(()=>{
|
|
508
|
+
if (IframeManager.iframeLoadPromise === loadPromise) {
|
|
509
|
+
IframeManager.iframeLoadPromise = null;
|
|
510
|
+
}
|
|
511
|
+
}).catch(()=>{
|
|
512
|
+
// Original rejection is delivered through the returned loadPromise.
|
|
513
|
+
});
|
|
514
|
+
return loadPromise;
|
|
457
515
|
}
|
|
458
516
|
assignExistingIframe() {
|
|
459
517
|
this.iframe = IframeManager.sharedIframe;
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/browser-wallet-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.340",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@dynamic-labs-wallet/core": "0.0.
|
|
7
|
+
"@dynamic-labs-wallet/core": "0.0.340",
|
|
8
8
|
"@dynamic-labs/logger": "^4.45.2",
|
|
9
9
|
"@dynamic-labs/message-transport": "^4.45.2"
|
|
10
10
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IframeManager.d.ts","sourceRoot":"","sources":["../../../src/client/iframeManager/IframeManager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAOR,KAAK,qBAAqB,EAE1B,KAAK,oBAAoB,EAE1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAML,KAAK,iCAAiC,EACtC,KAAK,cAAc,EACpB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"IframeManager.d.ts","sourceRoot":"","sources":["../../../src/client/iframeManager/IframeManager.ts"],"names":[],"mappings":"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"}
|