EPBDS-16211: make the orphan scan read TypeScript again - #152
Merged
Merged
Conversation
Appendix B's orphan scan looped over src/core/components/*.js. Since the TypeScript migration the pack has no .js file, so the scan checked no component. zsh rejects the empty glob. bash runs the loop once, on the literal pattern, and prints a single "198 *" line. The scan now finds the pack's .ts and .tsx files and gives the same output in bash and zsh. Re-run today, no pack file reads 0. A planted file with no importer reads 0. Its notes on reading the output are re-measured: the barrel's count is an artefact, files shares its name with modules/variables/files.ts, and the Tabs example went with the H6 rename. Appendix A's structure facts list what is gone as gone, each with the change that removed it: - the engine/form-modules cycle (#69); - Text's import of modules (#64); - the demo entries at the src/ root (#63). They also give the scan's new result, and the engine TabList's current path.
AlexSamBY
added a commit
that referenced
this pull request
Oct 2, 2026
…me (#153) ## What changes **`examples.strict-mode.test.js` now runs the animation frames on virtual time, as well as the timers.** The comparison still raced against the wall clock through the frames, which #149 left real. ### The failure A local `npm run test:coverage` run failed once, while #152 was gated. The test was "every example under StrictMode › tableForm renders, and reports, what it does without it", at `expect(strict.edited).toBe(plain.edited)`, and the rerun passed. After the edit, the two runs read the first date input differently: - **the plain run** read it with `value="an edit"`, and its picker still open, not yet aligned (`left: -1000vw`); - **the strict run** read it closed (`ui-render-picker-dropdown-hidden`), with the value reverted to `01-01-2022`. ### Why - **The picker opens, aligns and closes on animation frames,** through `rc-util/raf`. You can see it in rc-picker 4.11.3's `useDelayState`, `useLockEffect` and `Selector/Input`. - **#149 faked the timers and left `requestAnimationFrame` real.** Its comment said that nothing in the corpus needs frames faked. That was wrong for the picker. - **The 400 ms the test waits after an edit are virtual, and they pass in 1–3 ms of real time.** So whether a real frame landed in them was chance. A probe that counted frames found 2 of 3 plain runs on React 18 with no frame in that window, and each of them read the picker open. ### The fix `exercise()` no longer lists `requestAnimationFrame` and `cancelAnimationFrame` in `doNotFake`. A faked frame runs every 16 ms of the run's own clock. `Date`, the microtask queues and `setImmediate` stay real, as before. React's act and its scheduler use them, and no React version uses frames to schedule. ### Proof All three checks ran on React 16.14, 17.0.2, 18.3.1 and 19.3.0. **The new reads are the settled reads.** For each of the 76 runs (38 examples × 2 modes), I compared the mounted DOM, the edited DOM and the console output with the old reads taken after a 40 ms real hold, when the frames have run. All are identical. - A 40 ms hold no longer changes any read. - The new runs use no real frame. - With the old setup, only `tableForm` changed between three identical runs. That happened on React 16 and 18. On React 19 all three old runs read the picker open, against the settled read. React 17's sample happened not to vary. **The race is reproduced and closed.** I added a probe that withheld real frames from the plain run, and held the strict run for 40 ms after the blur, as a slow machine does. - The old test failed on `tableForm` on React 16 and 18, with the same `expect(strict.edited).toBe(plain.edited)` failure. - The new test passed on both. - The probe is removed. **It still catches StrictMode bugs.** I put back the dropdown mount flag that this test found when it was written. The new test failed on the same 7 examples as before. **It is not slower.** The file takes 1.4–1.7 s a leg, as it did. **It holds under the conditions that failed.** I ran the whole suite five times with `jest --coverage --runInBand`, the shape of `test:coverage`. All five passed, 2854 tests each. `docs/UPGRADE-PLAN.md` records the change beside the test's virtual-time note (§9.3 step 7). ## Gates All exited 0 on the first run, on this branch: - `lint:js`, `lint:css`, `typecheck`, `typecheck:contract`; - `docs:props:check`, `docs:views:check`, `css:fixture:check`; - `test:env-flags`, `build`; - `test:coverage`, thresholds included; - `test:pack`, `test:pack:peers`, `test:types`; - `test:react16`, `test:react17`, `test:react19`, 2854 tests each, with no worker crash; - `test:e2e`, 41 tests; - the manifest contract. The number of tests is unchanged. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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 changes
These are the two findings that #151 recorded and left for a change of their own. Both are in
docs/UPGRADE-PLAN.md.The orphan scan in Appendix B reads TypeScript again
It had checked no component since the TypeScript migration. It looped over
src/core/components/*.js, and the pack has no.jsfile now: it has 42.ts/.tsxfiles.no matches found: src/core/components/*.js, and nothing is printed.198 *: the pattern becomes/*', which matches every file that contains a'.The new command finds the pack's
.tsand.tsxfiles and strips either extension. It matches an import in either quote style, and leaves out the component's own file under either extension.How I checked it:
Its notes on reading the output are re-measured. The old ones described what the scan showed on 2026-09-17:
indexused to be "the only remaining 0". It now reads 5, and none of the five is the pack's barrel: three import the engine'sindex, and two are doc comments. The barrel itself is imported by directory path (from '../components'), which the pattern cannot see.filesreads 5, and two of the five importmodules/variables/files.ts. The old example,Tabs, went with the H6 rename.StandaloneTabsreads 1, and that one importer is the demo'sNavTabs.Appendix A's structure facts
Each fact that is gone is struck through and followed by the change that removed it, as the plan marks its other closed items:
components/Text.js:4importingmoduleswent with EPBDS-16211 H5: lock the layer direction in ESLint #64 (H5, 2026-09-23). The layer lint rejects both of these imports now.src/root moved tosrc/demo/with EPBDS-16211 H3/H4: isolate the demo, re-home the engine #63 (H3, 2026-09-23).Two more fixes in the same bullet:
TabList's path now also gives its current one,src/core/engine/components/TabList.tsx. This one was not in EPBDS-16211: stop the plan calling the Tabs duplicate open #151's list.There is no code change.
Gates
All exited 0 on this branch,
test:coverageon its second run:lint:js,lint:css,typecheck,typecheck:contract;docs:props:check,docs:views:check,css:fixture:check;test:env-flags,build;test:coverage, thresholds included;test:pack,test:pack:peers,test:types;test:react16,test:react17,test:react19, 2854 tests each, with no worker crash;test:e2e, 41 tests;The first
test:coveragerun failed one test, and this PR is not the cause.examples.strict-mode.test.jscompares each example's DOM after an edit, with and without StrictMode. OntableFormthe two runs read different DOM:This is the same kind of race #149 fixed, through animation frames instead of timers:
rc-util/raf. EPBDS-16211: compare the StrictMode runs on virtual time #149 leftrequestAnimationFrameon real time.The rerun passed all 2854 tests. The fix belongs in the test, in a change of its own.
🤖 Generated with Claude Code