|
| 1 | +# cypress-realworld-app — the holdout migrates green under the hardened adapter |
| 2 | + |
| 3 | +**Unit** `lrapr-t017b/g1-missing-export-tolerance` · **Role** holdout · **Result** migrated lane **green**, transform through emit |
| 4 | + |
| 5 | +This closes the strictly-later gap T017 named to the byte. T017 re-ran the holdout against the |
| 6 | +re-frozen adapter and stopped RED at one demand: a dangling named import in a self-inconsistent |
| 7 | +dependency ES module. This unit is an **authorized adapter reopen** (owner-directed 2026-08-13): |
| 8 | +the `5de7df56…` freeze is lifted for this hardening loop, the fingerprint fence is not enforced, |
| 9 | +and one generic capability is added to `packages/frameworks/react`. The prior RED records stay |
| 10 | +immutable and are advanced by reference. |
| 11 | + |
| 12 | +## The gap that was open |
| 13 | + |
| 14 | +T017 reached the rendering-chunks stage and failed with: |
| 15 | + |
| 16 | +``` |
| 17 | +[MISSING_EXPORT] "bpfrpt_proptype_WindowScroller" is not exported by |
| 18 | + "node_modules/react-virtualized/dist/es/WindowScroller/WindowScroller.js". |
| 19 | + ╭─[ node_modules/react-virtualized/dist/es/WindowScroller/utils/onScroll.js:74:10 ] |
| 20 | +74 │ import { bpfrpt_proptype_WindowScroller } from "../WindowScroller.js"; |
| 21 | +``` |
| 22 | + |
| 23 | +`react-virtualized` 9.22.3's `dist/es` build is produced with `babel-plugin-flow-react-proptypes`, |
| 24 | +which emits `import { bpfrpt_proptype_<Type> }` statements for flow proptype markers. Where the |
| 25 | +sibling module carries no runtime marker, the import dangles. webpack 4 resolved a dangling named |
| 26 | +import to `undefined`, so the baseline built; rolldown treats it as a hard error. |
| 27 | + |
| 28 | +## The capability added |
| 29 | + |
| 30 | +**Missing-export tolerance for a self-inconsistent dependency ES module.** When a dependency |
| 31 | +(node_modules) ES module imports a named binding the target module provably does not export, the |
| 32 | +binding is resolved to `undefined` — exactly webpack 4's outcome — under three guards, each |
| 33 | +enforced rather than asserted: |
| 34 | + |
| 35 | +- **Dependency modules only.** An application-source dangling import is a real first-party defect |
| 36 | + and is left for the bundler to report. |
| 37 | +- **Analyzer-proven absence.** The target is resolved and its actual export surface read; a name |
| 38 | + the target does export (directly, by named re-export, or behind an unresolved `export *`) is |
| 39 | + left exactly as written, and an unresolvable or bare-package target is never rewritten. |
| 40 | +- **Provably safe under `undefined`.** The binding is neutralized only when every reference to it |
| 41 | + is one the module's own evaluation does not dereference — a use inside a function body, an |
| 42 | + `export`/`import` alias that forwards the binding by name, a type-only position, or no use at |
| 43 | + all. A value read at module-evaluation scope is refused, so a genuine missing-export error still |
| 44 | + surfaces. |
| 45 | + |
| 46 | +The rewrite keeps the target module in the graph as a side-effect import so evaluation order is |
| 47 | +unchanged, and binds each neutralized name to `undefined`: |
| 48 | + |
| 49 | +``` |
| 50 | +import "../WindowScroller.js"; const bpfrpt_proptype_WindowScroller = void 0; |
| 51 | +``` |
| 52 | + |
| 53 | +The capability names no application, package, or marker. Nothing branches on the holdout's |
| 54 | +identity, revision, or source. |
| 55 | + |
| 56 | +## How narrow the shape actually is |
| 57 | + |
| 58 | +An analyzer sweep across all **28** files in that ES build that import a `bpfrpt_proptype_*` marker |
| 59 | +resolved each named relative import to its target and read the target's real export surface, |
| 60 | +following re-export chains. Exactly **one** import is genuinely absent from its target — |
| 61 | +`onScroll.js:74`, a **dead** import with zero references. The other 27 resolve through their |
| 62 | +`types.js` definitions or re-export chains and are left untouched. The one dangling case is dead, |
| 63 | +so it is safe under `undefined` by construction: module evaluation never reads it. |
| 64 | + |
| 65 | +## Result — migrated lane green |
| 66 | + |
| 67 | +The frozen-plus-capability `createCraViteAdapter` composition, applied through |
| 68 | +`fixtures/react-cypress-rwa/vite.config.ts` on Vite 8.0.16 / rolldown 1.0.3 with nothing |
| 69 | +holdout-specific in the config, now builds through to emit: |
| 70 | + |
| 71 | +``` |
| 72 | +✓ 10182 modules transformed. |
| 73 | +rendering chunks... |
| 74 | +✓ built in 2.65s |
| 75 | +``` |
| 76 | + |
| 77 | +Built **twice**, byte-identical: output digest |
| 78 | +`7051b8489abcaea1bd18ae99a082acf0c8d88596f1dfd82d6b4bac222e37dc18` over 18 emitted files |
| 79 | +(the 4.5 MB application chunk and its sourcemap, the split css/dom/core-js chunks, the CSS bundle, |
| 80 | +the generated `index.html`, and the replicated public assets). A measurement, not a flake. |
| 81 | + |
| 82 | +Three advisories print and none is fatal: an `INVALID_ANNOTATION` for a `/*@__PURE__*/` comment |
| 83 | +position in `@aws-amplify/ui-components`, an `EVAL` advisory for `vm-browserify`'s direct `eval`, |
| 84 | +and a chunk-size advisory for the single large application chunk. |
| 85 | + |
| 86 | +## Discipline |
| 87 | + |
| 88 | +Zero application source files were hand-edited. `src/aws-exports.js` and `aws-exports-es5.js` are |
| 89 | +copied by the application's own `predev:cognito:ci`; `index.html` is generated by the migration's |
| 90 | +`craEntryDocument` from the immutable `public/index.html`. The tolerance added is exactly |
| 91 | +webpack-4-dangling-DEPENDENCY-ESM-import→undefined — not a blanket missing-export suppression: |
| 92 | +application-source and value-position-used cases still fail. Network was used for nothing; the |
| 93 | +dependency closure was resident from the ingest under consent `VL-LEGACY-CORPUS-2026-08-10`, and |
| 94 | +every build ran offline. |
| 95 | + |
| 96 | +## Gate |
| 97 | + |
| 98 | +`pnpm exec tsc --noEmit` clean · `pnpm exec vp lint` 0 errors · `pnpm exec vp test --project node` |
| 99 | +2145/2145 (11 new tests for the capability: positive dead-import and deferred-use rewrites, the |
| 100 | +mixed-import split, and the app-source / value-position / present-export / unresolved-star / bare |
| 101 | +refusals, plus a build probe proving rolldown links the adapted build and refuses the unadapted |
| 102 | +one). |
| 103 | + |
| 104 | +## What is not claimed, and what comes next |
| 105 | + |
| 106 | +Build-level parity across both lanes is not claimed here — this record establishes that the |
| 107 | +migrated lane builds green, transform through emit. No runtime, boot, or behavioural parity is |
| 108 | +claimed, and no browser evidence exists for either lane. Witness journeys, an adapter re-freeze at |
| 109 | +a fresh boundary, and a PASSING holdout receipt (superseding the RED record by reference) are the |
| 110 | +follow-up units. |
0 commit comments