mirror of
https://github.com/Gitlawb/openclaude.git
synced 2026-08-24 02:34:15 -05:00
dist/cli.mjs shipped unminified at 21.7MB; whitespace+syntax minification cuts it to ~16MB (-26%) and shaves V8 parse time on every invocation. Identifier mangling stays off because the codebase matches constructor.name (errors.ts, toolExecution.ts, useCanUseTool). The SDK bundle stays unminified — its React/Ink leak check greps import syntax that minification would rewrite. The bundle guard's missing-module tripwire relied on Bun's `// missing-module-stub:<path>` module-boundary comments, which minification strips. The stub loader now also emits the marker as a side-effecting string push (survives treeshaking and syntax-minify), and the guard parses both forms. Review fix (CodeRabbit + jatmn): the marker parser previously truncated paths at the first backslash or space, so a JSON-escaped Windows marker like "missing-module-stub:C:\\Users\\Jane Doe\\...\\src\\...\\foo.js" was captured as a useless `C:` (or `C:\\Users\\Jane`) fragment and canonicalized to the wrong key — letting a newly stubbed module slip past the tripwire on Windows/spaced build hosts. Parse each marker form to its correct terminator instead: the string literal runs to its matching (back-ref) closing quote consuming escaped pairs, and Bun's comment runs to end of line. Extract canonicalStub() + the parser into scripts/stubMarkerGuard.ts so the logic is unit-testable, and add regression tests for Windows, spaced, comment-form, and multi-marker-per-line cases. Verified: build green, bundle ~16MB minified, guard passes against the real bundle, stub-guard tests pass, --version works through the minified bundle. Co-authored-by: OpenClaude <openclaude@gitlawb.com>
88 lines
3.9 KiB
TypeScript
88 lines
3.9 KiB
TypeScript
import { expect, test } from 'bun:test'
|
|
|
|
import { canonicalStub, collectBundleStubs } from './stubMarkerGuard.js'
|
|
|
|
test('canonicalStub keys on the src-relative path across separators', () => {
|
|
expect(canonicalStub('/home/runner/work/openclaude/openclaude/src/commands/dream/dream.ts')).toBe(
|
|
'src/commands/dream/dream',
|
|
)
|
|
// Windows separators normalize to the same key.
|
|
expect(canonicalStub('C:\\repo\\openclaude\\src\\commands\\dream\\dream.ts')).toBe(
|
|
'src/commands/dream/dream',
|
|
)
|
|
})
|
|
|
|
test('collectBundleStubs parses the JSON string-literal marker (minified builds)', () => {
|
|
const bundle = `;(globalThis.__openclaudeStubMarkers ??= []).push("missing-module-stub:/build/src/utils/foo.js");`
|
|
const stubbed = collectBundleStubs(bundle)
|
|
expect([...stubbed.keys()]).toEqual(['src/utils/foo'])
|
|
})
|
|
|
|
test('collectBundleStubs parses Bun module-boundary comments (unminified builds)', () => {
|
|
const bundle = `// missing-module-stub:/build/src/utils/foo.js\nvar foo = {};`
|
|
const stubbed = collectBundleStubs(bundle)
|
|
expect([...stubbed.keys()]).toEqual(['src/utils/foo'])
|
|
})
|
|
|
|
// Regression for the CodeRabbit/jatmn review on PR #1743: the marker regex
|
|
// previously excluded backslashes, so a JSON-escaped Windows path was captured
|
|
// as only `C:` and canonicalized to the wrong key — letting a newly stubbed
|
|
// module slip past the tripwire on Windows build hosts.
|
|
test('collectBundleStubs keeps Windows paths intact in the string-literal marker', () => {
|
|
// JSON.stringify doubles the backslashes, matching what ships in the bundle.
|
|
const marker = JSON.stringify('missing-module-stub:C:\\repo\\openclaude\\src\\commands\\dream\\dream.js')
|
|
const bundle = `;(globalThis.__openclaudeStubMarkers ??= []).push(${marker});`
|
|
|
|
const stubbed = collectBundleStubs(bundle)
|
|
|
|
// The canonical key must be the real src-relative path, not a `C:` fragment.
|
|
expect([...stubbed.keys()]).toEqual(['src/commands/dream/dream'])
|
|
expect(stubbed.has('src/commands/dream/dream')).toBe(true)
|
|
expect([...stubbed.keys()]).not.toContain('C:')
|
|
})
|
|
|
|
// Regression for the CodeRabbit follow-up on PR #1743: a checkout path with a
|
|
// space (e.g. `C:\Users\Jane Doe\...`) must survive to the canonical key. The
|
|
// terminator is the closing quote, not the first space.
|
|
test('collectBundleStubs keeps spaced Windows paths intact in the string-literal marker', () => {
|
|
const marker = JSON.stringify(
|
|
'missing-module-stub:C:\\Users\\Jane Doe\\openclaude\\src\\commands\\dream\\dream.js',
|
|
)
|
|
const bundle = `;(globalThis.__openclaudeStubMarkers ??= []).push(${marker});`
|
|
|
|
const stubbed = collectBundleStubs(bundle)
|
|
|
|
expect([...stubbed.keys()]).toEqual(['src/commands/dream/dream'])
|
|
expect([...stubbed.keys()]).not.toContain('C:')
|
|
})
|
|
|
|
test('collectBundleStubs keeps spaced paths intact in the comment marker', () => {
|
|
const bundle = `// missing-module-stub:/home/jane doe/openclaude/src/utils/foo.js\nvar foo = {};`
|
|
|
|
const stubbed = collectBundleStubs(bundle)
|
|
|
|
expect([...stubbed.keys()]).toEqual(['src/utils/foo'])
|
|
})
|
|
|
|
// jatmn's exact scenario: a Unix checkout under a spaced directory must resolve
|
|
// to the stable src/... key in the minified string-literal marker.
|
|
test('collectBundleStubs handles paths containing spaces', () => {
|
|
const marker = JSON.stringify(
|
|
'missing-module-stub:/Users/John Doe/projects/openclaude/src/utils/foo.js',
|
|
)
|
|
const bundle = `;(globalThis.__openclaudeStubMarkers ??= []).push(${marker});`
|
|
|
|
expect([...collectBundleStubs(bundle).keys()]).toEqual(['src/utils/foo'])
|
|
})
|
|
|
|
// A single minified line can hold several markers; greedy capture must stop at
|
|
// each closing quote rather than swallowing everything up to the last one.
|
|
test('collectBundleStubs parses multiple markers on one minified line', () => {
|
|
const bundle =
|
|
`.push("missing-module-stub:/b/src/a/one.js"),x.push("missing-module-stub:/b/src/a/two.js");`
|
|
|
|
const stubbed = collectBundleStubs(bundle)
|
|
|
|
expect(new Set(stubbed.keys())).toEqual(new Set(['src/a/one', 'src/a/two']))
|
|
})
|