refactor: replace hand-rolled parsers with standard packages#373
Open
latekvo wants to merge 5 commits into
Open
refactor: replace hand-rolled parsers with standard packages#373latekvo wants to merge 5 commits into
latekvo wants to merge 5 commits into
Conversation
Several utilities hand-rolled parsing that battle-tested packages (or deps already in the tree) do more reliably. Replaced the fragile cases: - adb AVD `.ini` + linux-preflight `config.ini` -> `ini` - workspace-reader `.env` key extraction -> `dotenv` - installer SKILL.md frontmatter `name:` -> `yaml` (already a dep) - installer escapeRegExp helper -> `escape-string-regexp` - xctrace / React Native version parsing -> `semver` (already a dep) - React `_debugStack` frame parsing -> `stacktrace-parser` Added regression tests for inputs the old code mishandled: quoted/ commented ini values, `export`-prefixed and multi-line .env entries, a frontmatter name with a trailing YAML comment, and line-only stack frames.
…ed-parsers # Conflicts: # package-lock.json # packages/argent-installer/package.json # packages/tool-server/package.json
A second full-codebase pass (covering the newly-merged Argent Lens / profiler
code) surfaced four more genuine reimplementations:
- registry zod→JSON-Schema converter -> Zod 4's native `z.toJSONSchema`
(io:"input"). The hand-rolled walk silently dropped every `.describe()` text
and `.min/.max/.int/.regex` constraint and emitted `{}` for unions — so the
schema the model sees for every tool was lossy.
- four MB-capped `formatBytes` helpers -> `bytes` (base-1024). Leak/asset
totals above 1 GB rendered as e.g. "2048.0 MB" instead of "2 GB".
- react-profiler `isWrappedInMemo` raw-source regex -> a tree-sitter pass
reusing the in-file `reactWrapperCall` (the regex matched `memo(...)` inside
comments/strings and ignored AST scope).
- network-interceptor detail script: hand-escaped `requestId` -> `JSON.stringify`
(the previous escaper injected a raw newline and crashed the runtime parse);
inspect-at-point aligned to the same.
Adds `bytes` (+ @types/bytes). Tests updated/added to cover the new behavior.
…ed-parsers # Conflicts: # packages/tool-server/src/utils/ios-profiler/export.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Swept the repo for hand-rolled regex/string parsers that reimplement a solved problem, and replaced the genuinely fragile ones with battle-tested packages (or deps already in the tree). Each swap is paired with a regression test for an input the old code got wrong.
adb.tsresolveAvdPath,linux-preflight.tsreadMb.ini/config.iniiniworkspace-reader.tsextractEnvKeys=line loopdotenv(parse)uninstall.tsreadBundledSkillName^name:(.+)$capture + outer-quote stripyaml(already a dep)mcp-configs.tsescapeRegExpescape-string-regexpexport.tsxctrace version,session-context.tsRN minormatch(/(\d+)\./)/split(".")[1]semvercoerce(already a dep)source-resolver.tsparseDebugStackat fn (file:l:c)regex (required both line+col)stacktrace-parserBugs these fix (covered by new tests)
path = "/Users/My Name/.../X.avd"kept its quotes, failed thestartsWith("/")guard → AVD unresolved. Inline comments / trailing junk after a sizing value made the anchored regex returnnull→ sizing warning silently lost.export FOO=barproduced the key"export FOO"(dropped by the identifier filter); a multi-line quoted value leaked its continuation lines (FAKE=...) as phantom keys.name:value with a trailing# commentwas taken verbatim (comment included); odd quoting only had one outer pair stripped.:line-only frame (no column, as Hermes/JSC can emit) became an unusableunknownframe.Deliberately left alone (not "flaky", or no safe swap)
To avoid churn and regressions, I did not touch:
uiautomator-parser.tshand-rolled XML parser — a deliberate, documented choice with a dedicated hardening suite, including a leniency test for malformed dumps (stray</node>). A spec XML parser would reject inputs this is built to recover from.ios-profiler/pipeline/xml-parser.ts(xctrace XML) — the most tangled parser, but it has no real.tracefixtures and only thin entity-decode tests. A rewrite can't be proven equivalent without device-generated traces, so swapping it blind risks silently breaking iOS CPU/hang/leak reports. Best done separately with a captured fixture.http.tsextractHostname— DNS-rebinding guard;URL.hostnamekeeps the IPv6 brackets the loopback check compares without, so the "fix" isn't simpler and the path is security-sensitive.adb.tsshellQuote— the POSIX single-quote escape is the standard correct form.parseAdbDevices,android-screen.tswm size,detect-app.tsdumpsys — tool-specific CLI-output scraping with no clean package equivalent (and documented edge-case handling).workspace-reader.tsextractMetroPort— a best-effort heuristic over JS config; a correct replacement needs an AST parse, out of scope here.config-parse.tsYarn/npm age-gate parsing — a precise, unit-tested domain parser;mswould introduce a bare-number ambiguity.Verification
tsc --buildclean across the workspace graph.prettier --checkclean on all changed files.bundle-tools.cjs) emits a validtool-server.cjs/mcp-server.mjswithini/dotenv/stacktrace-parserinlined (node --checkOK). (The script's final step errored only on the auth-gatedtrace-processor.wasmdownload, unrelated to bundling.)New runtime deps:
ini,dotenv,stacktrace-parser(tool-server),escape-string-regexp(installer) — all small, pure-JS. Lockfile change is purely additive.