ef2200f8ac
将 HostBridge 响应回放缓存上限提升到共享契约 让 Expo 移动壳复用共享缓存上限并拒绝本地重声明 让 Tauri 桌面壳配置检查反查共享缓存上限 补充两端回放缓存淘汰测试和壳方案文档
93 lines
2.5 KiB
TypeScript
93 lines
2.5 KiB
TypeScript
import {
|
|
HOST_BRIDGE_RESPONSE_CACHE_MAX,
|
|
type HostBridgeRequest,
|
|
type HostBridgeResponse,
|
|
normalizeHostBridgeRequestId,
|
|
} from '../../../../packages/shared/src/contracts/hostBridge';
|
|
import {
|
|
dispatchMobileHostBridgeRequest,
|
|
resetMobileHostBridgeDispatchForTest,
|
|
} from './dispatch';
|
|
import {
|
|
failure,
|
|
invalidRequest,
|
|
isHostBridgeRequest,
|
|
normalizeMobileHostBridgeError,
|
|
parseRequest,
|
|
} from './protocol';
|
|
|
|
export {
|
|
IOS_MOBILE_HOST_CAPABILITIES,
|
|
MOBILE_HOST_CAPABILITIES,
|
|
resolveMobileHostCapabilities,
|
|
} from './capabilities';
|
|
export { configureMobileHostBridgeNavigation } from './dispatch';
|
|
|
|
const completedHostBridgeResponses = new Map<string, HostBridgeResponse>();
|
|
const inFlightHostBridgeResponses = new Map<
|
|
string,
|
|
Promise<HostBridgeResponse>
|
|
>();
|
|
|
|
function rememberHostBridgeResponse(response: HostBridgeResponse) {
|
|
completedHostBridgeResponses.set(response.id, response);
|
|
if (completedHostBridgeResponses.size > HOST_BRIDGE_RESPONSE_CACHE_MAX) {
|
|
const oldestRequestId = completedHostBridgeResponses.keys().next().value;
|
|
if (oldestRequestId) {
|
|
completedHostBridgeResponses.delete(oldestRequestId);
|
|
}
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
async function resolveMobileHostBridgeResponse(request: HostBridgeRequest) {
|
|
const completedResponse = completedHostBridgeResponses.get(request.id);
|
|
if (completedResponse) {
|
|
return completedResponse;
|
|
}
|
|
|
|
const inFlightResponse = inFlightHostBridgeResponses.get(request.id);
|
|
if (inFlightResponse) {
|
|
return await inFlightResponse;
|
|
}
|
|
|
|
const responsePromise = dispatchMobileHostBridgeRequest(request)
|
|
.catch((error: unknown) =>
|
|
failure(request, normalizeMobileHostBridgeError(error)),
|
|
)
|
|
.then(rememberHostBridgeResponse);
|
|
inFlightHostBridgeResponses.set(request.id, responsePromise);
|
|
|
|
try {
|
|
return await responsePromise;
|
|
} finally {
|
|
inFlightHostBridgeResponses.delete(request.id);
|
|
}
|
|
}
|
|
|
|
export async function handleMobileHostBridgeMessage(
|
|
rawMessage: string,
|
|
sendResponse: (response: HostBridgeResponse) => void,
|
|
) {
|
|
const parsed = parseRequest(rawMessage);
|
|
if (!isHostBridgeRequest(parsed)) {
|
|
sendResponse(
|
|
failure(
|
|
{ id: 'invalid' },
|
|
invalidRequest('invalid host bridge request'),
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
|
|
parsed.id = normalizeHostBridgeRequestId(parsed.id) ?? parsed.id;
|
|
sendResponse(await resolveMobileHostBridgeResponse(parsed));
|
|
}
|
|
|
|
export function resetMobileHostBridgeForTest() {
|
|
resetMobileHostBridgeDispatchForTest();
|
|
completedHostBridgeResponses.clear();
|
|
inFlightHostBridgeResponses.clear();
|
|
}
|