From abf3174c6a78e167b9f3fe4f33bc865fcfc31321 Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 20 Jun 2026 13:31:56 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=81=E5=AE=9A=E5=BE=AE=E4=BF=A1=E4=B9=9D?= =?UTF-8?q?=E5=AE=AB=E5=88=87=E5=9B=BE=E5=A4=B1=E8=B4=A5=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 微信九宫切图失败不再向页面透出原生错误细节 微信九宫切图测试覆盖原生下载失败稳定提示 native shell 总门禁反查微信九宫切图失败边界 --- miniprogram/shell/shareGrid.js | 19 ++++++++---- miniprogram/shell/shareGrid.test.js | 25 ++++++++++++++++ scripts/check-native-shells.mjs | 46 +++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/miniprogram/shell/shareGrid.js b/miniprogram/shell/shareGrid.js index 2a02c9625..07ff03ff8 100644 --- a/miniprogram/shell/shareGrid.js +++ b/miniprogram/shell/shareGrid.js @@ -7,6 +7,13 @@ const { normalizeShareGridQuery, } = require('../host-bridge/shareGrid'); +const WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE = '九宫切图保存失败。'; + +function rejectShareGridSaveFailure(reject, label, error) { + console.error(`[share-grid] ${label}`, error); + reject(new Error(WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE)); +} + function downloadImage(imageUrl) { return new Promise((resolve, reject) => { wx.downloadFile({ @@ -19,7 +26,7 @@ function downloadImage(imageUrl) { reject(new Error(`封面下载失败:${response.statusCode}`)); }, fail(error) { - reject(new Error(error.errMsg || '封面下载失败')); + rejectShareGridSaveFailure(reject, 'download failed', error); }, }); }); @@ -31,7 +38,7 @@ function getImageInfo(src) { src, success: resolve, fail(error) { - reject(new Error(error.errMsg || '读取封面失败')); + rejectShareGridSaveFailure(reject, 'read image info failed', error); }, }); }); @@ -67,7 +74,7 @@ function canvasToTempFilePath(canvas, width, height) { resolve(response.tempFilePath); }, fail(error) { - reject(new Error(error.errMsg || '导出切图失败')); + rejectShareGridSaveFailure(reject, 'export tile failed', error); }, }); }); @@ -81,7 +88,7 @@ function saveImageToAlbum(filePath) { resolve(); }, fail(error) { - reject(new Error(error.errMsg || '保存到相册失败')); + rejectShareGridSaveFailure(reject, 'save album failed', error); }, }); }); @@ -194,8 +201,7 @@ function createWechatShareGridPage() { } catch (error) { console.error('[share-grid] save failed', error); this.setData({ - errorMessage: - error && error.message ? error.message : '九宫切图保存失败。', + errorMessage: WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE, loading: false, }); } @@ -208,5 +214,6 @@ function createWechatShareGridPage() { } module.exports = { + WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE, createWechatShareGridPage, }; diff --git a/miniprogram/shell/shareGrid.test.js b/miniprogram/shell/shareGrid.test.js index 7ea62e7a8..f5754011e 100644 --- a/miniprogram/shell/shareGrid.test.js +++ b/miniprogram/shell/shareGrid.test.js @@ -46,4 +46,29 @@ describe('wechat share-grid shell page', () => { expect(page.data.loading).toBe(false); expect(page.data.errorMessage).toBe('缺少封面图。'); }); + + test('hides downloadFile native failure details from the page', async () => { + const consoleError = vi + .spyOn(console, 'error') + .mockImplementation(() => undefined); + globalThis.wx.downloadFile = vi.fn(({ fail }) => { + fail({ errMsg: 'private native download detail' }); + }); + const page = createPage(); + + await page.onLoad({ + imageUrl: 'https://web.test/cover.png', + title: '九宫切图', + publicWorkCode: 'PZ-0001', + }); + + expect(page.data.loading).toBe(false); + expect(page.data.errorMessage).toBe('九宫切图保存失败。'); + expect(page.data.errorMessage).not.toContain('private native download detail'); + expect(consoleError).toHaveBeenCalledWith( + '[share-grid] download failed', + { errMsg: 'private native download detail' }, + ); + consoleError.mockRestore(); + }); }); diff --git a/scripts/check-native-shells.mjs b/scripts/check-native-shells.mjs index 8b2c9f39f..193557412 100644 --- a/scripts/check-native-shells.mjs +++ b/scripts/check-native-shells.mjs @@ -1988,6 +1988,49 @@ function assertWechatAuthFailureBoundaries() { } } +function assertWechatShareGridFailureBoundaries() { + const shareGridSource = fs.readFileSync( + 'miniprogram/shell/shareGrid.js', + 'utf8', + ); + const shareGridTestSource = fs.readFileSync( + 'miniprogram/shell/shareGrid.test.js', + 'utf8', + ); + + for (const snippet of [ + "WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE = '九宫切图保存失败。'", + "console.error(`[share-grid] ${label}`, error)", + 'reject(new Error(WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE))', + 'errorMessage: WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE', + ]) { + if (!shareGridSource.includes(snippet)) { + throw new Error(`wechat share-grid shell must include ${snippet}`); + } + } + for (const forbiddenSnippet of [ + "reject(new Error(error.errMsg || '封面下载失败'))", + "reject(new Error(error.errMsg || '读取封面失败'))", + "reject(new Error(error.errMsg || '导出切图失败'))", + "reject(new Error(error.errMsg || '保存到相册失败'))", + "error && error.message ? error.message : '九宫切图保存失败。'", + ]) { + if (shareGridSource.includes(forbiddenSnippet)) { + throw new Error(`wechat share-grid shell must not expose native failure detail via ${forbiddenSnippet}`); + } + } + for (const snippet of [ + 'hides downloadFile native failure details from the page', + "expect(page.data.errorMessage).toBe('九宫切图保存失败。')", + "expect(page.data.errorMessage).not.toContain('private native download detail')", + "expect(consoleError).toHaveBeenCalledWith(", + ]) { + if (!shareGridTestSource.includes(snippet)) { + throw new Error(`wechat share-grid boundary test must include ${snippet}`); + } + } +} + function assertHostBridgeLayerLayout() { assertSameList( readDirectoryFileList( @@ -2224,6 +2267,9 @@ assertWechatSubscribeResultBoundaries(); console.log('[check:native-shells] wechat-auth-failure-boundaries'); assertWechatAuthFailureBoundaries(); +console.log('[check:native-shells] wechat-share-grid-failure-boundaries'); +assertWechatShareGridFailureBoundaries(); + console.log('[check:native-shells] h5-host-bridge-event-subscription-gates'); assertH5HostBridgeEventSubscriptionGates();