From 35d7c698e99795833e54b1bfb1d0e566e64ad06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KET=20=E2=9A=A1?= Date: Thu, 15 Oct 2026 23:22:53 +0530 Subject: [PATCH] fix(hooks): read BOM-prefixed managed hook preferences --- scripts/lib/hook-flags.js | 2 +- tests/hooks/hook-flags.test.js | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/scripts/lib/hook-flags.js b/scripts/lib/hook-flags.js index 69d3f25d6..c453bdb04 100644 --- a/scripts/lib/hook-flags.js +++ b/scripts/lib/hook-flags.js @@ -48,7 +48,7 @@ function readManagedHookConfig(env = process.env) { if (!configPath || !fs.existsSync(configPath)) return {}; try { - const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); + const config = JSON.parse(fs.readFileSync(configPath, 'utf8').replace(/^\uFEFF/, '')); return config?.hooks && typeof config.hooks === 'object' && !Array.isArray(config.hooks) diff --git a/tests/hooks/hook-flags.test.js b/tests/hooks/hook-flags.test.js index 9e566edbf..9b8a3c806 100644 --- a/tests/hooks/hook-flags.test.js +++ b/tests/hooks/hook-flags.test.js @@ -162,6 +162,22 @@ function runTests() { } })) passed++; else failed++; + if (test('managed hook config accepts a leading UTF-8 BOM', () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-hook-flags-bom-')); + const configPath = path.join(root, 'setup.json'); + const env = { ECC_HOOK_CONFIG: configPath }; + try { + fs.writeFileSync(configPath, '\uFEFF' + JSON.stringify({ + hooks: { enabled: false, profile: 'minimal', note: 'keep\uFEFFinside' }, + })); + assert.strictEqual(areHooksEnabled(env), false); + assert.strictEqual(getHookProfile(env), 'minimal'); + assert.strictEqual(readManagedHookConfig(env).note, 'keep\uFEFFinside'); + } finally { + fs.rmSync(root, { recursive: true, force: true }); + } + })) passed++; else failed++; + if (test('a hook evaluation reads managed config only once', () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-hook-flags-read-once-')); const configPath = path.join(root, 'setup.json');