Skip to content

Commit 3046aaa

Browse files
committed
revert(truapi): drop iframe MessagePort handshake from this PR
The truapi-ready/truapi-init handshake pairs with the WASM host's createIframeHost (#104). Keep sandbox.ts at base so merging to main does not break the deployed playground against the current host.
1 parent 9fbaaf4 commit 3046aaa

1 file changed

Lines changed: 18 additions & 97 deletions

File tree

js/packages/truapi/src/sandbox.ts

Lines changed: 18 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
*/
1212

1313
import {
14+
createIframeProvider,
1415
createMessagePortProvider,
1516
type WireProvider,
1617
} from "./transport.js";
@@ -61,7 +62,10 @@ export function isCorrectEnvironment(): boolean {
6162
}
6263

6364
/**
64-
* Origin used as the `targetOrigin` for iframe bootstrap messages.
65+
* Origin used as the `targetOrigin` for outbound `postMessage` frames. Frames
66+
* carry signed payloads and account ids, so this fails closed: when no concrete
67+
* origin can be pinned it returns `null` (rather than falling back to `"*"`) and
68+
* provider construction throws.
6569
*/
6670
function resolveHostOrigin(): string | null {
6771
if (typeof document !== "undefined" && document.referrer) {
@@ -76,8 +80,7 @@ function resolveHostOrigin(): string | null {
7680
return null;
7781
}
7882

79-
const HOST_PORT_TIMEOUT_MS = 20_000;
80-
let iframePortPromise: Promise<MessagePort> | null = null;
83+
const WEBVIEW_PORT_TIMEOUT_MS = 20_000;
8184

8285
/**
8386
* Resolve the host-injected `MessagePort`, polling `window.__HOST_API_PORT__`
@@ -90,7 +93,7 @@ let iframePortPromise: Promise<MessagePort> | null = null;
9093
*/
9194
async function waitForWebviewPort(
9295
signal?: AbortSignal,
93-
timeoutMs = HOST_PORT_TIMEOUT_MS,
96+
timeoutMs = WEBVIEW_PORT_TIMEOUT_MS,
9497
): Promise<MessagePort> {
9598
const start = Date.now();
9699
while (Date.now() - start < timeoutMs) {
@@ -104,93 +107,18 @@ async function waitForWebviewPort(
104107
);
105108
}
106109

107-
/**
108-
* Resolve the iframe `MessagePort` transferred by `createIframeHost`.
109-
*/
110-
function waitForIframePort(
111-
signal?: AbortSignal,
112-
timeoutMs = HOST_PORT_TIMEOUT_MS,
113-
): Promise<MessagePort> {
114-
const existing = hostWindow()?.__HOST_API_PORT__;
115-
if (existing) return Promise.resolve(existing);
116-
if (iframePortPromise) return iframePortPromise;
117-
118-
iframePortPromise = new Promise<MessagePort>((resolve, reject) => {
119-
const win = hostWindow();
120-
if (!win) {
121-
reject(new Error("window is unavailable"));
122-
return;
123-
}
124-
125-
const hostOrigin = resolveHostOrigin();
126-
let done = false;
127-
const cleanup = (): void => {
128-
win.removeEventListener("message", onMessage);
129-
signal?.removeEventListener("abort", onAbort);
130-
clearTimeout(timer);
131-
};
132-
const finish = (result: MessagePort | Error): void => {
133-
if (done) return;
134-
done = true;
135-
cleanup();
136-
if (result instanceof Error) {
137-
reject(result);
138-
} else {
139-
win.__HOST_API_PORT__ = result;
140-
resolve(result);
141-
}
142-
};
143-
const onAbort = (): void => {
144-
finish(new Error("waitForIframePort aborted"));
145-
};
146-
const onMessage = (event: MessageEvent): void => {
147-
if (event.source !== win.parent) return;
148-
if (
149-
hostOrigin !== null &&
150-
event.origin !== hostOrigin &&
151-
event.origin !== "null"
152-
) {
153-
return;
154-
}
155-
if (event.data?.type !== "truapi-init") return;
156-
const [port] = event.ports;
157-
if (!port) {
158-
finish(new Error("truapi-init did not include a MessagePort"));
159-
return;
160-
}
161-
finish(port);
162-
};
163-
const timer = setTimeout(() => {
164-
finish(
165-
new Error(`Timed out waiting for iframe MessagePort (${timeoutMs}ms)`),
166-
);
167-
}, timeoutMs);
168-
169-
win.addEventListener("message", onMessage);
170-
signal?.addEventListener("abort", onAbort, { once: true });
171-
win.parent.postMessage({ type: "truapi-ready" }, hostOrigin ?? "*");
172-
}).catch((error: unknown) => {
173-
iframePortPromise = null;
174-
throw error;
175-
});
176-
177-
return iframePortPromise;
178-
}
179-
180110
/** Build the {@link WireProvider} matching the detected environment (iframe or webview). */
181111
function createSandboxProvider(): WireProvider {
182-
const portController = new AbortController();
183112
if (isIframe()) {
184-
const provider = createMessagePortProvider(
185-
waitForIframePort(portController.signal),
186-
);
187-
const baseDispose = provider.dispose;
188-
provider.dispose = () => {
189-
portController.abort();
190-
baseDispose?.();
191-
};
192-
return provider;
113+
const hostOrigin = resolveHostOrigin();
114+
if (!hostOrigin) {
115+
throw new Error(
116+
"TrUAPI iframe provider could not resolve the host origin from document.referrer / ancestorOrigins.",
117+
);
118+
}
119+
return createIframeProvider({ target: window.parent, hostOrigin });
193120
}
121+
const portController = new AbortController();
194122
const provider = createMessagePortProvider(
195123
waitForWebviewPort(portController.signal),
196124
);
@@ -238,21 +166,14 @@ export function getClientSync(): TrUApiClient | null {
238166
export function subscribeConnectionStatus(
239167
callback: (status: ConnectionStatus) => void,
240168
): () => void {
241-
let emitted = false;
242-
const listener = (next: ConnectionStatus) => {
243-
emitted = true;
244-
callback(next);
245-
};
246-
statusListeners.add(listener);
169+
statusListeners.add(callback);
170+
callback(status);
247171

248172
if (status === "disconnected") {
249173
setStatus(getClientSync() ? "connected" : "disconnected");
250174
}
251-
if (!emitted) {
252-
callback(status);
253-
}
254175

255176
return () => {
256-
statusListeners.delete(listener);
177+
statusListeners.delete(callback);
257178
};
258179
}

0 commit comments

Comments
 (0)