diff --git a/README.md b/README.md index 2a60eb7..5206019 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ + + + 友情推荐 + 友情推荐 diff --git a/electron/main-process/bounded-output-buffer.js b/electron/main-process/bounded-output-buffer.js new file mode 100644 index 0000000..ab98de2 --- /dev/null +++ b/electron/main-process/bounded-output-buffer.js @@ -0,0 +1,22 @@ +const DEFAULT_MAX_OUTPUT_CHARS = 256 * 1024; + +function appendBoundedOutput(currentOutput, nextChunk, maxChars = DEFAULT_MAX_OUTPUT_CHARS) { + if (!Number.isFinite(maxChars) || maxChars <= 0) { + return ''; + } + + const current = typeof currentOutput === 'string' ? currentOutput : ''; + const next = Buffer.isBuffer(nextChunk) ? nextChunk.toString() : String(nextChunk ?? ''); + const combined = current + next; + + if (combined.length <= maxChars) { + return combined; + } + + return combined.slice(-maxChars); +} + +module.exports = { + DEFAULT_MAX_OUTPUT_CHARS, + appendBoundedOutput, +}; diff --git a/electron/main-process/mihomo-service.js b/electron/main-process/mihomo-service.js index 41bdf75..133b06d 100644 --- a/electron/main-process/mihomo-service.js +++ b/electron/main-process/mihomo-service.js @@ -17,6 +17,7 @@ module.exports = function initMihomoService(context) { const { applyOverrides } = require('../ipc-handlers/overrides'); const { getMihomoControllerParam, cleanupSocketFile } = require('../utils/socket-path'); const { RunningMode, setRunningMode, getRunningMode, isServiceMode, getSocketPath, getServiceSocketPath, getSidecarSocketPath } = require('../utils/running-mode'); + const { appendBoundedOutput } = require('./bounded-output-buffer'); console.log('[mihomo-service] applyOverrides函数已导入:', typeof applyOverrides); async function waitForProcessExit(proc, timeoutMs = 5000) { @@ -1200,7 +1201,7 @@ module.exports = function initMihomoService(context) { spawnedProcess.stdout.on('data', (data) => { const logContent = data.toString(); - stdoutOutput += logContent; // 收集 stdout 输出 + stdoutOutput = appendBoundedOutput(stdoutOutput, logContent); // 收集最近的 stdout 输出 console.log(`mihomo stdout: ${logContent}`); // 检测 TUN 启动失败 @@ -1258,7 +1259,7 @@ module.exports = function initMihomoService(context) { spawnedProcess.stderr.on('data', (data) => { const errorText = data.toString(); - stderrOutput += errorText; // 收集 stderr 输出 + stderrOutput = appendBoundedOutput(stderrOutput, errorText); // 收集最近的 stderr 输出 console.error(`mihomo stderr: ${errorText}`); safeSend('mihomo-error', errorText); process.stderr.write(data); diff --git a/package.json b/package.json index 4301bb5..694776d 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "build": "next build", "start": "next start", "lint": "next lint", + "test": "node --test", "rebuild:native": "electron-rebuild -f -w better-sqlite3", "postinstall": "electron-builder install-app-deps", "prepare": "node scripts/prepare.mjs", diff --git a/test/bounded-output-buffer.test.js b/test/bounded-output-buffer.test.js new file mode 100644 index 0000000..7511ab6 --- /dev/null +++ b/test/bounded-output-buffer.test.js @@ -0,0 +1,30 @@ +const assert = require('node:assert/strict'); +const test = require('node:test'); + +const { + DEFAULT_MAX_OUTPUT_CHARS, + appendBoundedOutput, +} = require('../electron/main-process/bounded-output-buffer'); + +test('appendBoundedOutput keeps short output unchanged', () => { + const output = appendBoundedOutput('hello', '\nworld', 32); + + assert.equal(output, 'hello\nworld'); +}); + +test('appendBoundedOutput caps retained output and keeps newest content', () => { + let output = ''; + + output = appendBoundedOutput(output, '12345', 10); + output = appendBoundedOutput(output, '67890', 10); + output = appendBoundedOutput(output, 'abcde', 10); + + assert.equal(output, '67890abcde'); + assert.equal(output.length, 10); +}); + +test('appendBoundedOutput truncates a single large chunk to the configured limit', () => { + const output = appendBoundedOutput('', 'x'.repeat(DEFAULT_MAX_OUTPUT_CHARS + 5), 16); + + assert.equal(output, 'x'.repeat(16)); +});