From fba6fb75fb9ce4a6d7462c0307207faa14c20ee9 Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 20 Jun 2026 13:43:48 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=81=E5=AE=9A=E5=BE=AE=E4=BF=A1=E5=8E=9F?= =?UTF-8?q?=E7=94=9F=E9=A1=B5=E8=B7=B3=E8=BD=AC=E5=A4=B1=E8=B4=A5=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit H5 HostBridge 微信小程序跳转失败不再透出原生 errMsg HostBridge 测试覆盖微信跳转失败稳定提示 native shell 总门禁反查微信跳转失败边界 --- scripts/check-native-shells.mjs | 25 +++++++++++++++ src/services/host-bridge/hostBridge.test.ts | 34 +++++++++++++++++++++ src/services/host-bridge/hostBridge.ts | 6 +++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/scripts/check-native-shells.mjs b/scripts/check-native-shells.mjs index ec8e329de..44fc94e12 100644 --- a/scripts/check-native-shells.mjs +++ b/scripts/check-native-shells.mjs @@ -1027,6 +1027,10 @@ function assertH5HostBridgePayloadBoundaries() { 'src/services/host-bridge/hostBridge.ts', 'utf8', ); + const h5HostBridgeTestSource = fs.readFileSync( + 'src/services/host-bridge/hostBridge.test.ts', + 'utf8', + ); const nativeRequestCapabilities = extractTsStringArray( sharedContractSource, 'HOST_BRIDGE_METHODS', @@ -1117,6 +1121,27 @@ function assertH5HostBridgePayloadBoundaries() { 'H5 HostBridge facade must reject unsafe native app navigation targets before sending navigation.openNativePage', ); } + if ( + !h5HostBridgeSource.includes( + "'[host-bridge] wechat mini program navigation failed'", + ) || + !h5HostBridgeSource.includes('reject(new Error(errorMessage));') || + h5HostBridgeSource.includes('reject(new Error(error?.errMsg || errorMessage));') + ) { + throw new Error( + 'H5 HostBridge facade must not expose wx.miniProgram.navigateTo native failures', + ); + } + for (const snippet of [ + 'hides wechat mini program navigation native failure details', + "errMsg: 'navigateTo:fail private native detail'", + "rejects.toThrow(\n '请在微信小程序内完成登录',", + "rejects.not.toThrow(\n 'private native detail',", + ]) { + if (!h5HostBridgeTestSource.includes(snippet)) { + throw new Error(`H5 HostBridge navigation failure test must include ${snippet}`); + } + } if ( !h5HostBridgeSource.includes( 'absolutizeHostSharePayloadUrls(params),', diff --git a/src/services/host-bridge/hostBridge.test.ts b/src/services/host-bridge/hostBridge.test.ts index f6df3597a..d242cd125 100644 --- a/src/services/host-bridge/hostBridge.test.ts +++ b/src/services/host-bridge/hostBridge.test.ts @@ -767,6 +767,40 @@ describe('hostBridge', () => { await expect(requestWechatMiniProgramPhoneLogin()).resolves.toBe(true); }); + test('hides wechat mini program navigation native failure details', async () => { + const consoleError = vi + .spyOn(console, 'error') + .mockImplementation(() => undefined); + const navigationError = { + errMsg: 'navigateTo:fail private native detail', + }; + const navigateTo = vi.fn((options) => { + options.fail?.(navigationError); + }); + window.history.replaceState( + null, + '', + '/?clientRuntime=wechat_mini_program', + ); + window.wx = { + miniProgram: { + navigateTo, + }, + }; + + await expect(requestHostLogin()).rejects.toThrow( + '请在微信小程序内完成登录', + ); + await expect(requestHostLogin()).rejects.not.toThrow( + 'private native detail', + ); + expect(consoleError).toHaveBeenCalledWith( + '[host-bridge] wechat mini program navigation failed', + navigationError, + ); + consoleError.mockRestore(); + }); + test('通过微信小程序原生页请求支付', async () => { const navigateTo = vi.fn((options) => { options.success?.(); diff --git a/src/services/host-bridge/hostBridge.ts b/src/services/host-bridge/hostBridge.ts index a3b53c76c..583cadc3a 100644 --- a/src/services/host-bridge/hostBridge.ts +++ b/src/services/host-bridge/hostBridge.ts @@ -496,7 +496,11 @@ export async function navigateWechatMiniProgramPage( resolve(); }, fail(error) { - reject(new Error(error?.errMsg || errorMessage)); + console.error( + '[host-bridge] wechat mini program navigation failed', + error, + ); + reject(new Error(errorMessage)); }, }); });