From 9efb04da84b0703e25927cf25aff6f15ba866bd0 Mon Sep 17 00:00:00 2001 From: Alex Newman Date: Fri, 5 Jun 2026 20:36:18 -0700 Subject: [PATCH] fix(hooks): bun-runner.js parses on pre-ES2020 Node (closes #2791) (#2801) The Stop hook crashes every session with 'SyntaxError: Unexpected token .' when a host invokes bun-runner.js under a bundled pre-ES2020 Node whose ESM loader rejects optional chaining (?.). Replace the only ?. site with explicit guards and add a build-time guard forbidding ?. / ?? in this launcher so it can't regress. Co-authored-by: Claude Opus 4.8 (1M context) --- plugin/scripts/bun-runner.js | 10 +++++++++- scripts/build-hooks.js | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/plugin/scripts/bun-runner.js b/plugin/scripts/bun-runner.js index 929fd35af..0c2b3c462 100644 --- a/plugin/scripts/bun-runner.js +++ b/plugin/scripts/bun-runner.js @@ -66,7 +66,15 @@ function isPluginDisabledInClaudeSettings() { const settingsPath = join(configDir, 'settings.json'); if (!existsSync(settingsPath)) return false; const settings = JSON.parse(readFileSync(settingsPath, 'utf-8')); - return settings?.enabledPlugins?.['claude-mem@thedotmack'] === false; + // No optional chaining (?.) here: this launcher must parse on the oldest + // Node that any host might invoke it with. Some Claude Code installs run + // hooks under a bundled pre-ES2020 Node whose ESM loader throws + // "SyntaxError: Unexpected token '.'" on `?.` (issue #2791). + return Boolean( + settings && + settings.enabledPlugins && + settings.enabledPlugins['claude-mem@thedotmack'] === false + ); } catch { return false; } diff --git a/scripts/build-hooks.js b/scripts/build-hooks.js index f773b8e30..bc83530aa 100644 --- a/scripts/build-hooks.js +++ b/scripts/build-hooks.js @@ -175,6 +175,19 @@ async function verifyShellTemplateCanonical() { ); } + // Parser-compat guard (issue #2791): bun-runner.js is invoked by hosts that + // may run a pre-ES2020 Node whose ESM loader throws on optional chaining. + // Strip comments, then forbid `?.` / `??` in executable code. + const bunRunnerCode = bunRunner + .replace(/\/\*[\s\S]*?\*\//g, '') + .replace(/(^|[^:])\/\/.*$/gm, '$1'); + if (/\?\.|\?\?/.test(bunRunnerCode)) { + throw new Error( + 'plugin/scripts/bun-runner.js uses optional chaining (?.) or nullish coalescing (??) — ' + + 'this launcher must parse on pre-ES2020 Node (issue #2791). Rewrite with explicit guards.' + ); + } + console.log('✓ Rule A shell templates match the canonical generator'); }