记录移动返回栈同步失败
移动 WebView 返回栈注入脚本写入 history state 失败时记录日志 移动壳测试和配置检查拒绝返回栈脚本空 catch 共享决策日志补充移动返回栈同步失败边界
This commit is contained in:
@@ -1520,12 +1520,20 @@ for (const snippet of [
|
||||
'genarrative.mobile.historyState',
|
||||
'__genarrativeMobileHistoryIndex',
|
||||
'__GENARRATIVE_MOBILE_POST_NAVIGATION_STATE__',
|
||||
"console.warn('mobile navigation state sync failed', error)",
|
||||
]) {
|
||||
if (!webViewPolicySource.includes(snippet)) {
|
||||
throw new Error(`mobile shell WebView policy missing ${snippet}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
webViewPolicySource.includes('catch (error) {}') ||
|
||||
webViewPolicySource.includes('catch (_error) {}')
|
||||
) {
|
||||
throw new Error('mobile shell WebView policy must not hide injected script failures');
|
||||
}
|
||||
|
||||
if (
|
||||
webViewPolicySource.includes("['blob:'") ||
|
||||
webViewPolicySource.includes("'filesystem:'")
|
||||
|
||||
@@ -169,6 +169,32 @@ describe('TRACK_MOBILE_WEBVIEW_HISTORY_SCRIPT', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('路由栈状态写入失败时记录日志', () => {
|
||||
const postMessage = vi.fn();
|
||||
const syncError = new Error('history state blocked');
|
||||
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
window.ReactNativeWebView = {
|
||||
postMessage,
|
||||
};
|
||||
window.history.replaceState = vi.fn(() => {
|
||||
throw syncError;
|
||||
}) as typeof window.history.replaceState;
|
||||
|
||||
window.eval(TRACK_MOBILE_WEBVIEW_HISTORY_SCRIPT);
|
||||
|
||||
expect(warnSpy).toHaveBeenCalledWith(
|
||||
'mobile navigation state sync failed',
|
||||
syncError,
|
||||
);
|
||||
expect(postMessage).toHaveBeenCalledWith(
|
||||
JSON.stringify({
|
||||
type: 'genarrative.mobile.historyState',
|
||||
canGoBack: false,
|
||||
}),
|
||||
);
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
test('重复注入时回放当前 H5 路由栈状态', () => {
|
||||
const postMessage = vi.fn();
|
||||
window.ReactNativeWebView = {
|
||||
|
||||
@@ -176,7 +176,9 @@ export const TRACK_MOBILE_WEBVIEW_HISTORY_SCRIPT = `
|
||||
'',
|
||||
window.location.href
|
||||
);
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
console.warn('mobile navigation state sync failed', error);
|
||||
}
|
||||
}
|
||||
|
||||
window.history.pushState = function(state, title, url) {
|
||||
|
||||
@@ -2958,6 +2958,13 @@
|
||||
- 影响范围:`apps/mobile-shell/src/shell/ShellApp.tsx`、`apps/mobile-shell/src/shell/ShellApp.test.tsx`、`apps/mobile-shell/scripts/check-config.mjs`。
|
||||
- 验证方式:`npm run mobile-shell:test -- src/shell/ShellApp.test.tsx`、`npm run mobile-shell:typecheck`、`npm run check:native-shells`、`npm run check:encoding`、`git diff --check`。
|
||||
|
||||
## 2026-06-20 移动壳返回栈状态同步失败不可静默
|
||||
|
||||
- 背景:Expo 移动壳通过 WebView 注入脚本追踪当前 H5 文档 history index 并回传 `navigation.canGoBack`;如果 `replaceState(...)` 写入 index 失败后静默吞掉,Android 返回键和 H5 返回按钮状态可能漂移且难以排查。
|
||||
- 决策:`TRACK_MOBILE_WEBVIEW_HISTORY_SCRIPT` 的 `replaceCurrentState()` catch 路径必须输出 `mobile navigation state sync failed` 浏览器 console 警告,同时继续回传当前可返回状态;移动壳配置检查拒绝该注入脚本重新出现空 catch。
|
||||
- 影响范围:`apps/mobile-shell/src/shell/webViewPolicy.ts`、`apps/mobile-shell/src/shell/webViewPolicy.test.ts`、`apps/mobile-shell/scripts/check-config.mjs`。
|
||||
- 验证方式:`npm run mobile-shell:test -- src/shell/webViewPolicy.test.ts`、`npm run mobile-shell:typecheck`、`npm run check:native-shells`、`npm run check:encoding`、`git diff --check`。
|
||||
|
||||
## 2026-06-20 移动壳生命周期映射门禁
|
||||
|
||||
- 背景:Expo `AppState` 的 `active`、`background`、`inactive` 以及未知状态都会进入 `app.lifecycle` 事件;如果归一化映射漂移,H5 游戏循环、背景音乐和固定玩法音频会错误恢复或暂停。
|
||||
|
||||
Reference in New Issue
Block a user