@floegence/redevplugin-ui 3.0.28 → 3.0.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/dist/surface.d.ts +5 -0
- package/dist/surface.js +56 -21
- package/dist/trusted-parent.d.ts +1 -1
- package/package.json +2 -2
package/dist/surface.d.ts
CHANGED
|
@@ -455,9 +455,14 @@ export type PluginSurfaceHostBootstrap = {
|
|
|
455
455
|
runtimeGenerationId: string;
|
|
456
456
|
};
|
|
457
457
|
export type PluginSurfaceHostContext = PluginSurfaceContext;
|
|
458
|
+
export type PluginSurfaceOpeningStage = "preparing" | "connecting" | "authorizing" | "initializing" | "committing";
|
|
459
|
+
export type PluginSurfaceOpeningMilestone = "frame_load" | "prepare" | "port_ack" | "token" | "renderer_ready" | "worker_ready" | "first_commit";
|
|
458
460
|
export type PluginSurfaceOpeningProgress = {
|
|
459
461
|
phase: "opening";
|
|
460
462
|
elapsedMs: number;
|
|
463
|
+
stage: PluginSurfaceOpeningStage;
|
|
464
|
+
stageElapsedMs: number;
|
|
465
|
+
pendingMilestones: PluginSurfaceOpeningMilestone[];
|
|
461
466
|
};
|
|
462
467
|
export type PluginSurfaceInteractionKind = "activation" | "focus" | "wheel" | "text-selection" | "action";
|
|
463
468
|
export type PluginSurfaceInteractionEvent = {
|
package/dist/surface.js
CHANGED
|
@@ -2586,10 +2586,10 @@ export function createOpaquePluginBootstrapHTML(options = {}) {
|
|
|
2586
2586
|
currentContext = message.context;
|
|
2587
2587
|
try { applyStaticDocument(currentDocument); if (currentContext) applySurfaceContext(currentContext); startWorker(currentDocument); }
|
|
2588
2588
|
catch (error) { return fail(error); }
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2589
|
+
// Readiness describes applied initialization, not a browser paint. Hidden
|
|
2590
|
+
// and offscreen opaque frames may never receive an animation frame.
|
|
2591
|
+
sendParent({ type: "redevplugin.surface.renderer_ready" });
|
|
2592
|
+
loadAssets();
|
|
2593
2593
|
return;
|
|
2594
2594
|
}
|
|
2595
2595
|
if (isRecord(message) && exactKeys(message, ["type", "frame_generation_id", "surface_handle", "context"]) && message.type === "redevplugin.surface.context" && message.frame_generation_id === frameGenerationID && message.surface_handle === surfaceHandle && validSurfaceContext(message.context)) {
|
|
@@ -2687,6 +2687,10 @@ class PluginSurfaceHostImplementation {
|
|
|
2687
2687
|
#port;
|
|
2688
2688
|
#openSignals;
|
|
2689
2689
|
#openingFailure;
|
|
2690
|
+
#openingStartedAt = 0;
|
|
2691
|
+
#openingStageStartedAt = 0;
|
|
2692
|
+
#openingStage = "preparing";
|
|
2693
|
+
#openingPending = new Set();
|
|
2690
2694
|
#quiesce;
|
|
2691
2695
|
#initialFrameLoad;
|
|
2692
2696
|
#frameLoaded = false;
|
|
@@ -2742,23 +2746,22 @@ class PluginSurfaceHostImplementation {
|
|
|
2742
2746
|
}
|
|
2743
2747
|
this.#opened = true;
|
|
2744
2748
|
this.#openingFailure = undefined;
|
|
2745
|
-
|
|
2746
|
-
|
|
2749
|
+
this.#openingStartedAt = performance.now();
|
|
2750
|
+
this.#setOpeningStage("preparing", ["frame_load", "prepare"]);
|
|
2751
|
+
const progressTimer = setInterval(() => {
|
|
2747
2752
|
if (!this.#ready && !this.#disposed) {
|
|
2748
|
-
this.#
|
|
2749
|
-
|
|
2750
|
-
elapsedMs: Math.max(openingProgressDelayMs, Date.now() - startedAt),
|
|
2751
|
-
});
|
|
2753
|
+
const progress = this.#openingProgress();
|
|
2754
|
+
this.#reportOpeningProgress({ ...progress, elapsedMs: Math.max(openingProgressDelayMs, progress.elapsedMs) });
|
|
2752
2755
|
}
|
|
2753
2756
|
}, openingProgressDelayMs);
|
|
2754
2757
|
const signals = {
|
|
2755
2758
|
portAcknowledged: deferred(),
|
|
2756
|
-
|
|
2759
|
+
rendererReady: deferred(),
|
|
2757
2760
|
workerReady: deferred(),
|
|
2758
2761
|
firstCommit: deferred(),
|
|
2759
2762
|
};
|
|
2760
2763
|
void signals.portAcknowledged.promise.catch(() => undefined);
|
|
2761
|
-
void signals.
|
|
2764
|
+
void signals.rendererReady.promise.catch(() => undefined);
|
|
2762
2765
|
void signals.workerReady.promise.catch(() => undefined);
|
|
2763
2766
|
void signals.firstCommit.promise.catch(() => undefined);
|
|
2764
2767
|
this.#openSignals = signals;
|
|
@@ -2773,9 +2776,11 @@ class PluginSurfaceHostImplementation {
|
|
|
2773
2776
|
await withTimeout(this.#completeOpening(signals, initialFrameLoad.promise), this.#loadTimeoutMs, "Plugin surface opening timed out");
|
|
2774
2777
|
}
|
|
2775
2778
|
catch (error) {
|
|
2776
|
-
|
|
2777
|
-
if (bridgeError.errorCode === "PLUGIN_BRIDGE_TIMEOUT")
|
|
2779
|
+
let bridgeError = this.#openingFailure ?? toBridgeError(error, "PLUGIN_BRIDGE_HANDSHAKE_FAILED");
|
|
2780
|
+
if (bridgeError.errorCode === "PLUGIN_BRIDGE_TIMEOUT") {
|
|
2781
|
+
bridgeError = new PluginBridgeError(bridgeError.errorCode, bridgeError.message, undefined, this.#openingProgress(), bridgeError.mutationOutcome);
|
|
2778
2782
|
this.#reloadLimiter.recordCrash();
|
|
2783
|
+
}
|
|
2779
2784
|
this.#reportError(bridgeError);
|
|
2780
2785
|
const revoke = this.#revokeSurface(false);
|
|
2781
2786
|
this.#disposeLocal();
|
|
@@ -2783,20 +2788,28 @@ class PluginSurfaceHostImplementation {
|
|
|
2783
2788
|
throw bridgeError;
|
|
2784
2789
|
}
|
|
2785
2790
|
finally {
|
|
2786
|
-
|
|
2791
|
+
clearInterval(progressTimer);
|
|
2792
|
+
this.#openingPending.clear();
|
|
2787
2793
|
this.#openSignals = undefined;
|
|
2788
2794
|
this.#openingFailure = undefined;
|
|
2789
2795
|
this.#initialFrameLoad = undefined;
|
|
2790
2796
|
}
|
|
2791
2797
|
}
|
|
2792
2798
|
async #completeOpening(signals, initialFrameLoad) {
|
|
2793
|
-
const [preparation] = await Promise.all([
|
|
2799
|
+
const [preparation] = await Promise.all([
|
|
2800
|
+
this.#prepareSurface().then((value) => {
|
|
2801
|
+
this.#openingPending.delete("prepare");
|
|
2802
|
+
return value;
|
|
2803
|
+
}),
|
|
2804
|
+
initialFrameLoad.then(() => { this.#openingPending.delete("frame_load"); }),
|
|
2805
|
+
]);
|
|
2794
2806
|
this.#assertActive();
|
|
2795
2807
|
validateSurfacePreparation(this.bootstrap, preparation);
|
|
2796
2808
|
this.#assetSession = preparation.asset_session;
|
|
2797
2809
|
this.#assetSessionID = preparation.asset_session_id;
|
|
2798
2810
|
this.#document = preparation.document;
|
|
2799
2811
|
this.#assets = new Map(preparation.document.assets.map((asset) => [asset.binding_id, asset]));
|
|
2812
|
+
this.#setOpeningStage("connecting", ["port_ack"]);
|
|
2800
2813
|
const channel = this.#createMessageChannel();
|
|
2801
2814
|
this.#port = channel.port1;
|
|
2802
2815
|
this.#port.addEventListener("message", this.#onPortMessage);
|
|
@@ -2811,9 +2824,11 @@ class PluginSurfaceHostImplementation {
|
|
|
2811
2824
|
}, "*", [channel.port2]);
|
|
2812
2825
|
await signals.portAcknowledged.promise;
|
|
2813
2826
|
this.#assertActive();
|
|
2827
|
+
this.#setOpeningStage("authorizing", ["token"]);
|
|
2814
2828
|
const token = await this.#mintBridgeToken();
|
|
2815
2829
|
this.#assertActive();
|
|
2816
2830
|
this.#applyLease(token);
|
|
2831
|
+
this.#setOpeningStage("initializing", ["renderer_ready", "worker_ready"]);
|
|
2817
2832
|
this.#postToRenderer(removeUndefined({
|
|
2818
2833
|
type: "redevplugin.surface.initialize",
|
|
2819
2834
|
frame_generation_id: this.frameGenerationId,
|
|
@@ -2822,10 +2837,11 @@ class PluginSurfaceHostImplementation {
|
|
|
2822
2837
|
context: this.#surfaceContext,
|
|
2823
2838
|
}));
|
|
2824
2839
|
this.#rendererInitialized = true;
|
|
2825
|
-
await Promise.all([signals.
|
|
2840
|
+
await Promise.all([signals.rendererReady.promise, signals.workerReady.promise]);
|
|
2826
2841
|
this.#assertActive();
|
|
2827
2842
|
this.#bridgeReady = true;
|
|
2828
2843
|
this.#scheduleLeaseRenewal();
|
|
2844
|
+
this.#setOpeningStage("committing", ["first_commit"]);
|
|
2829
2845
|
this.#postToRenderer({ type: "redevplugin.bridge.lifecycle", event: { type: "ready" } });
|
|
2830
2846
|
await signals.firstCommit.promise;
|
|
2831
2847
|
this.#assertActive();
|
|
@@ -2921,7 +2937,7 @@ class PluginSurfaceHostImplementation {
|
|
|
2921
2937
|
controller.abort();
|
|
2922
2938
|
this.#pendingRequestControllers.clear();
|
|
2923
2939
|
const disposedError = new PluginBridgeError("PLUGIN_BRIDGE_DISPOSED", "Plugin surface host was disposed");
|
|
2924
|
-
this.#openSignals?.
|
|
2940
|
+
this.#openSignals?.rendererReady.reject(disposedError);
|
|
2925
2941
|
this.#openSignals?.workerReady.reject(disposedError);
|
|
2926
2942
|
this.#openSignals?.firstCommit.reject(disposedError);
|
|
2927
2943
|
this.#openSignals?.portAcknowledged.reject(disposedError);
|
|
@@ -2969,20 +2985,24 @@ class PluginSurfaceHostImplementation {
|
|
|
2969
2985
|
}
|
|
2970
2986
|
if (!messageWithinLimit(data))
|
|
2971
2987
|
return;
|
|
2972
|
-
if (hasExactKeys(data, ["type"]) && data.type === "redevplugin.surface.
|
|
2973
|
-
this.#
|
|
2988
|
+
if (hasExactKeys(data, ["type"]) && data.type === "redevplugin.surface.renderer_ready") {
|
|
2989
|
+
this.#openingPending.delete("renderer_ready");
|
|
2990
|
+
this.#openSignals?.rendererReady.resolve();
|
|
2974
2991
|
return;
|
|
2975
2992
|
}
|
|
2976
2993
|
if (hasExactKeys(data, ["type", "frame_generation_id"]) &&
|
|
2977
2994
|
data.type === "redevplugin.surface.port_ack" && data.frame_generation_id === this.frameGenerationId) {
|
|
2995
|
+
this.#openingPending.delete("port_ack");
|
|
2978
2996
|
this.#openSignals?.portAcknowledged.resolve();
|
|
2979
2997
|
return;
|
|
2980
2998
|
}
|
|
2981
2999
|
if (hasExactKeys(data, ["type"]) && data.type === "redevplugin.surface.worker_ready") {
|
|
3000
|
+
this.#openingPending.delete("worker_ready");
|
|
2982
3001
|
this.#openSignals?.workerReady.resolve();
|
|
2983
3002
|
return;
|
|
2984
3003
|
}
|
|
2985
3004
|
if (hasExactKeys(data, ["type"]) && data.type === "redevplugin.surface.first_commit") {
|
|
3005
|
+
this.#openingPending.delete("first_commit");
|
|
2986
3006
|
this.#openSignals?.firstCommit.resolve();
|
|
2987
3007
|
return;
|
|
2988
3008
|
}
|
|
@@ -3528,7 +3548,7 @@ class PluginSurfaceHostImplementation {
|
|
|
3528
3548
|
this.#rendererInitialized = false;
|
|
3529
3549
|
const terminalError = opening ? (this.#openingFailure ??= error) : error;
|
|
3530
3550
|
this.#openSignals?.portAcknowledged.reject(terminalError);
|
|
3531
|
-
this.#openSignals?.
|
|
3551
|
+
this.#openSignals?.rendererReady.reject(terminalError);
|
|
3532
3552
|
this.#openSignals?.workerReady.reject(terminalError);
|
|
3533
3553
|
this.#openSignals?.firstCommit.reject(terminalError);
|
|
3534
3554
|
if (!opening)
|
|
@@ -3583,6 +3603,21 @@ class PluginSurfaceHostImplementation {
|
|
|
3583
3603
|
// Observers cannot weaken revocation or local teardown invariants.
|
|
3584
3604
|
}
|
|
3585
3605
|
}
|
|
3606
|
+
#setOpeningStage(stage, pending) {
|
|
3607
|
+
this.#openingStage = stage;
|
|
3608
|
+
this.#openingStageStartedAt = performance.now();
|
|
3609
|
+
this.#openingPending = new Set(pending);
|
|
3610
|
+
}
|
|
3611
|
+
#openingProgress() {
|
|
3612
|
+
const now = performance.now();
|
|
3613
|
+
return {
|
|
3614
|
+
phase: "opening",
|
|
3615
|
+
elapsedMs: Math.max(0, Math.floor(now - this.#openingStartedAt)),
|
|
3616
|
+
stage: this.#openingStage,
|
|
3617
|
+
stageElapsedMs: Math.max(0, Math.floor(now - this.#openingStageStartedAt)),
|
|
3618
|
+
pendingMilestones: [...this.#openingPending],
|
|
3619
|
+
};
|
|
3620
|
+
}
|
|
3586
3621
|
#reportOpeningProgress(progress) {
|
|
3587
3622
|
try {
|
|
3588
3623
|
this.#onOpeningProgress?.(progress);
|
package/dist/trusted-parent.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ export * from "./errors.js";
|
|
|
3
3
|
export * from "./platform.js";
|
|
4
4
|
export { PluginSurfaceScope, createPluginSurfaceScope } from "./surface-scope.js";
|
|
5
5
|
export { PluginSurfaceReloadLimiter, PluginSurfaceSlot, createReDevPluginSurfaceTransport, defaultPluginSurfaceReloadMax, defaultPluginSurfaceReloadWindowMs, isPluginRiskPlan, opaqueSurfaceDocumentSchemaVersion, pluginSurfaceContextSchemaVersion, pluginRiskPlanSchemaVersion, pluginSurfaceFileExportActionWindowMs, pluginSurfaceFileExportMaxBytes, pluginSurfaceFileExportMediaTypes, trustedParentBridgeHandshakeTranscriptSHA256, } from "./surface.js";
|
|
6
|
-
export type { BridgeLifecycleEvent, MessageChannelLike, MessageEventLike, MessagePortLike, OpaqueSurfaceAsset, OpaqueSurfaceDocument, OpaqueSurfaceStyle, OpaqueSurfaceWorker, PluginConfirmationDecision, PluginConfirmationHandler, PluginConfirmationIntent, PluginConfirmationPlan, PluginMethodResult, PluginRiskEffect, PluginRiskFlag, PluginRiskPlan, PluginRiskSeverity, PluginExecutionEvent, PluginSurfaceHost, PluginSurfaceCloseResult, PluginSurfaceOpeningProgress, PluginSurfaceInteractionEvent, PluginSurfaceInteractionKind, PluginSurfaceFileExport, PluginSurfaceFileExportHandler, PluginSurfaceFileExportMediaType, PluginSurfaceQuiesceResult, PluginSurfaceRevocationReconciliation, PluginSurfacePreparationResult, PluginSurfaceContext, PluginSurfaceReloadDecision, PluginSurfaceReloadLimiterOptions, PluginSurfaceReloadState, PluginSurfaceSlotOptions, PluginSurfaceSlotState, ReDevPluginSurfaceTransport, ReDevPluginSurfaceTransportOptions, TrustedParentBridgeHandshake, TrustedParentBridgeTokenRequest, WindowLike, } from "./surface.js";
|
|
6
|
+
export type { BridgeLifecycleEvent, MessageChannelLike, MessageEventLike, MessagePortLike, OpaqueSurfaceAsset, OpaqueSurfaceDocument, OpaqueSurfaceStyle, OpaqueSurfaceWorker, PluginConfirmationDecision, PluginConfirmationHandler, PluginConfirmationIntent, PluginConfirmationPlan, PluginMethodResult, PluginRiskEffect, PluginRiskFlag, PluginRiskPlan, PluginRiskSeverity, PluginExecutionEvent, PluginSurfaceHost, PluginSurfaceCloseResult, PluginSurfaceOpeningProgress, PluginSurfaceOpeningStage, PluginSurfaceOpeningMilestone, PluginSurfaceInteractionEvent, PluginSurfaceInteractionKind, PluginSurfaceFileExport, PluginSurfaceFileExportHandler, PluginSurfaceFileExportMediaType, PluginSurfaceQuiesceResult, PluginSurfaceRevocationReconciliation, PluginSurfacePreparationResult, PluginSurfaceContext, PluginSurfaceReloadDecision, PluginSurfaceReloadLimiterOptions, PluginSurfaceReloadState, PluginSurfaceSlotOptions, PluginSurfaceSlotState, ReDevPluginSurfaceTransport, ReDevPluginSurfaceTransportOptions, TrustedParentBridgeHandshake, TrustedParentBridgeTokenRequest, WindowLike, } from "./surface.js";
|
|
7
7
|
export type { FetchInitLike, FetchLike, FetchResponseLike, PlatformResponse } from "./http.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@floegence/redevplugin-ui",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.29",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"dist"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@floegence/redevplugin-contracts": "3.0.
|
|
43
|
+
"@floegence/redevplugin-contracts": "3.0.29"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|