收口移动运行时桥接边界

将 Expo host.getRuntime 回包组装收口到 runtime 模块

让移动 dispatch 只委托运行时请求

同步移动壳结构门禁、架构文档和共享记忆
This commit is contained in:
2026-06-19 23:09:55 +08:00
parent c3b2c73879
commit ffe7bda460
7 changed files with 51 additions and 34 deletions
+19 -7
View File
@@ -42,6 +42,8 @@ const notificationsPath = new URL('../src/host-bridge/notifications.ts', import.
const notificationsSource = fs.readFileSync(notificationsPath, 'utf8');
const protocolPath = new URL('../src/host-bridge/protocol.ts', import.meta.url);
const protocolSource = fs.readFileSync(protocolPath, 'utf8');
const hostBridgeRuntimePath = new URL('../src/host-bridge/runtime.ts', import.meta.url);
const hostBridgeRuntimeSource = fs.readFileSync(hostBridgeRuntimePath, 'utf8');
const sharePath = new URL('../src/host-bridge/share.ts', import.meta.url);
const shareSource = fs.readFileSync(sharePath, 'utf8');
const bridgeDirPath = new URL('../src/host-bridge/', import.meta.url);
@@ -107,6 +109,7 @@ const requiredMobileShellSourceModules = [
'host-bridge/network.ts',
'host-bridge/notifications.ts',
'host-bridge/protocol.ts',
'host-bridge/runtime.ts',
'host-bridge/scanner.ts',
'host-bridge/share.ts',
'shell/QrScannerOverlay.tsx',
@@ -1771,26 +1774,35 @@ if (!shellAppSource.includes('hostVersion: MOBILE_SHELL_HOST_VERSION')) {
throw new Error('mobile shell URL must use the shared mobile shell host version');
}
if (!dispatchSource.includes('hostVersion: MOBILE_SHELL_HOST_VERSION')) {
if (!hostBridgeRuntimeSource.includes('hostVersion: MOBILE_SHELL_HOST_VERSION')) {
throw new Error('mobile shell runtime response must use the shared mobile shell host version');
}
for (const runtimeSnippet of [
'function getMobileRuntimePlatform()',
'export function getMobileRuntimePlatform()',
"return Platform.OS === 'ios' ? 'ios' : 'android'",
'function getRuntime()',
'export function getMobileHostBridgeRuntime(): HostBridgeRuntimeResult',
'const platform = getMobileRuntimePlatform();',
'platform,',
'capabilities: resolveMobileHostCapabilities(platform)',
"case 'host.getRuntime':",
'return ok(request, getRuntime());',
]) {
if (!dispatchSource.includes(runtimeSnippet)) {
if (!hostBridgeRuntimeSource.includes(runtimeSnippet)) {
throw new Error(`mobile shell runtime response missing ${runtimeSnippet}`);
}
}
if (dispatchSource.includes('capabilities: resolveMobileHostCapabilities(),')) {
if (
!dispatchSource.includes('getMobileHostBridgeRuntime()') ||
dispatchSource.includes('MOBILE_SHELL_HOST_VERSION') ||
dispatchSource.includes('HOST_BRIDGE_VERSION') ||
dispatchSource.includes('resolveMobileHostCapabilities(') ||
dispatchSource.includes('getMobileRuntimePlatform') ||
dispatchSource.includes("shell: 'expo_mobile'")
) {
throw new Error('mobile shell dispatch must delegate host.getRuntime to runtime.ts');
}
if (hostBridgeRuntimeSource.includes('capabilities: resolveMobileHostCapabilities(),')) {
throw new Error(
'mobile shell runtime capabilities must use the same normalized platform reported in host.getRuntime',
);
+3 -23
View File
@@ -1,12 +1,6 @@
import * as Linking from 'expo-linking';
import { Platform } from 'react-native';
import {
HOST_BRIDGE_VERSION,
type HostBridgeRequest,
} from '../../../../packages/shared/src/contracts/hostBridge';
import { MOBILE_SHELL_HOST_VERSION } from '../shell/runtime';
import { resolveMobileHostCapabilities } from './capabilities';
import { type HostBridgeRequest } from '../../../../packages/shared/src/contracts/hostBridge';
import {
captureImageFile,
exportAudioFile,
@@ -43,6 +37,7 @@ import {
reloadMobileHostBridgeWebView,
} from './navigation';
import { getMobileHostBridgeNetworkStatus } from './network';
import { getMobileHostBridgeRuntime } from './runtime';
let navigation: MobileHostBridgeNavigation | null = null;
@@ -52,27 +47,12 @@ export function configureMobileHostBridgeNavigation(
navigation = nextNavigation;
}
function getMobileRuntimePlatform() {
return Platform.OS === 'ios' ? 'ios' : 'android';
}
function getRuntime() {
const platform = getMobileRuntimePlatform();
return {
shell: 'expo_mobile',
platform,
hostVersion: MOBILE_SHELL_HOST_VERSION,
bridgeVersion: HOST_BRIDGE_VERSION,
capabilities: resolveMobileHostCapabilities(platform),
};
}
export async function dispatchMobileHostBridgeRequest(
request: HostBridgeRequest,
) {
switch (request.method) {
case 'host.getRuntime':
return ok(request, getRuntime());
return ok(request, getMobileHostBridgeRuntime());
case 'appearance.getColorScheme':
return ok(request, getMobileAppearanceColorScheme());
case 'app.openExternalUrl':
@@ -0,0 +1,23 @@
import { Platform } from 'react-native';
import {
HOST_BRIDGE_VERSION,
type HostBridgeRuntimeResult,
} from '../../../../packages/shared/src/contracts/hostBridge';
import { MOBILE_SHELL_HOST_VERSION } from '../shell/runtime';
import { resolveMobileHostCapabilities } from './capabilities';
export function getMobileRuntimePlatform() {
return Platform.OS === 'ios' ? 'ios' : 'android';
}
export function getMobileHostBridgeRuntime(): HostBridgeRuntimeResult {
const platform = getMobileRuntimePlatform();
return {
shell: 'expo_mobile',
platform,
hostVersion: MOBILE_SHELL_HOST_VERSION,
bridgeVersion: HOST_BRIDGE_VERSION,
capabilities: resolveMobileHostCapabilities(platform),
};
}