feat(parser): static fiber reconstruction from source ASTs with runtime verification harness - #115
feat(parser): static fiber reconstruction from source ASTs with runtime verification harness#115aidenybai wants to merge 10 commits into
Conversation
Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
…ate, fixture suite Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
… components, native external values Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
…outes, derived-external uncertainty Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
…Meta, Links, ScrollRestoration); template matches runtime exactly Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
… bulletproof-react), capture replay, namespace rest/spread, README Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
Original prompt from Aiden Bai
|
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
commit: |
Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
…valuator gaps - lowered/compiled class recognition (Babel _createClass, prototype assignment, Component.call) - error boundary throw propagation with getDerivedStateFromError/componentDidCatch - isolated vs outer-provider context semantics - tagged templates, RegExp, Map/Set/Promise, reduce, scheduling globals - optional list items for uncertain filters; structural equivalence for recursion cutoff - callable globals (Boolean/String/Number) as array callbacks - vite ssr anonymous default export naming normalized Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
…ber output Replace the handwritten FiberBuilder/host-semantics/serializer with a Materializer: interpreter values become React elements whose source components are proxies calling back into the interpreter, rendered with the project's react-dom in happy-dom and captured with bippy. Uncertainty is kept as marker components ($Branch/$Repeat/$Opaque/$Unknown/$Text) so the captured tree doubles as the comparison pattern. Proxies are keyed by closure (node + scope) so HOCs applied twice yield distinct component types. Hook state is threaded through real React state so effect-driven setState settles before capture. Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
Summary
Adds
packages/parser(@bippy/parser, private): static reconstruction of React fiber trees from source ASTs, plus a harness that captures the real tree through bippy and compares the two against 20 pinned real-world repositories. Application code is never executed for analysis — but the fibers are real, built by React's own reconciler.One strategy: the interpreter understands the source, React constructs the tree.
Materializerturns evaluated element values into elements of the project's ownreact(resolved through the module graph); every source-defined function/class component becomes a same-named proxy whose render callsInterpreter.callFunctionon the source body, andmemo/forwardRef/lazy/contexts/Fragment/StrictMode/Suspense/portals/host tags map to the real React APIs. Work tags,shouldSetTextContent, hoistables/singletons, memo bailouts and error boundaries are therefore React's, not a reimplementation (the earlier hand-writtenFiberBuilder/host-semanticsmirror is gone). Proxy identity is the source closure (node+scope), so a HOC applied twice yields two component types, as at runtime. Hook cells live in a per-proxyHookFramedriven by realuseState/useEffect, sosetStatefrom effects re-renders and settles before capture.Uncertainty is materialized, not guessed: marker components
$Branch/$Alternative,$Repeat,$Opaque(passed children rendered inside),$Unknown,$Textare ordinary fibers in the captured tree at the position of the uncertainty. The comparer reads the materialized tree back into a pattern (snapshotToPattern) — a marker-free tree is a plain fiber-by-fiber diff (tag, name, key, text, order); markers become try-each-alternative / absorb-any-count / slot-into-library-subtree / wildcard — and reportsexact/partial/mismatch/unresolved/skippedwith coverage and the first divergence path.exactis only claimed when no uncertainty was consumed.What is modeled
export *chains, barrels, cycles, ambiguous exports. External packages are opaque unless allow-listed or modeled by a framework adapter.jsx/jsxs/jsxDEV/createElement,_extends/_objectWithoutProperties, compiled classes),props.children, bounded list ops and imperative loops, hooks (useState/useReducercells,useContext/usevia nearest provider,useSyncExternalStoreserver snapshot,useIdunknown text, effects with dep tracking), class components (fields, ctor, inheritance,this.state,setState, error boundaries),Object.assigncomponent patterns, tagged templates, HOC composition,awaitin server/awaited contexts. Budgets on depth/recursion/branch fan-out/steps/element count; exhaustion is an$Unknown, never a confident truncation.renderFramework({ framework, entry?, route? })):spa,next-app(layout/template/page/loading composition, async server components, client boundaries, Next externals; RSC mode elides server components like the Flight client),next-pages(_app),react-router(route configs,lazyroutes,HydratedRouter/RouterProvider, rootLayout/App,Meta/Links/ScrollRestoration,react-router-auto-routesconventions). Each has aFrameworkProfilenaming only framework wrapper fibers as transparent — every name was added after observing it in a real capture, never to hide an application mismatch.Corpus (
corpus/manifest.json, results incorpus/results.json)20 pinned repos (actual, bulletproof-react, cal-diy, epic-stack, excalidraw, graphiql, invoify, lexical, nextjs-boilerplate, nextjs-examples, puck, react-admin, react-email, react-router-templates, redux-toolkit, shadcn-ui, sonner, tanstack-query, tanstack-router, tldraw). All 20 render through the materializer with their own React (18.3 – 19.3 canary). Verified against a live dev server + Playwright:
<meta>is a side effect, not a fibercal-diyis recorded as blocked (needs Postgres + app-store env); the rest are static-only in this environment.pnpm corpus -- --static-onlyreplays the saved capture (.corpus/.out/<id>.capture.json) when one exists, so evaluator changes are re-checked against the same runtime tree without a dev server.Tests / wiring
tests/components/*: 35 single-file component conformance fixtures (hooks/state+effects, context, class components, error boundaries, compiled classic/automatic JSX, HOCs, tagged templates, hoistables, suspending data, recursion, i18n, forms…), each rendered statically and independently mounted withreact-dom; the two fiber trees must match.tests/fixtures/*: 19 synthetic projects (compiled JSX, class state, portals, memo/forwardRef/lazy, re-export cycles, spread props, text normalization, opaque/derived externals, react-router data/jsx/lazy).tests/framework-fixtures/*: Next App/Pages Router andreact-router-auto-routeslayouts.pnpm testincludes theparservite project; rootpnpm typecheckruns@bippy/parser typecheck.packages/parser/README.mddocuments the pipeline, value model, materialization, comparison semantics, corpus methodology and limitations.Link to Devin session: https://app.devin.ai/sessions/b6d14be3cb7742979b56c7d7772cb48b
Open in Devin Desktop: https://app.devin.ai/desktop/session/b6d14be3cb7742979b56c7d7772cb48b?variant=devin
Requested by: @aidenybai