mirror of
https://github.com/software-mansion/argent.git
synced 2026-09-14 19:27:14 +08:00
0f4d5e51cc
## Defect In `packages/tool-server/src/utils/react-profiler/pipeline/03-tag.ts`, the animation-detection regex was both unanchored and case-insensitive: ```ts const ANIMATED_PATTERN = /(Animated|Animation|Transition|Motion)/i; ``` Because of the `/i` flag, the token `Motion` matches the lowercase substring "motion" that appears inside perfectly ordinary PascalCase component names: `PromotionCard`, `EmotionThemeCard`, `CommotionList`, `LocomotionView`, and so on. Those components get tagged `isAnimated = true` in stage 3, and stage 4 (`04-rank.ts`) then unconditionally drops every animated component from the findings (`if (comp.isAnimated) continue;`). The result: a genuinely slow or frequently re-rendering component such as `PromotionCard` silently disappears from the report's Top Components / Suggested Improvements, even though it is exactly the kind of component the profiler exists to surface. `ProductCard` (no "motion" substring) is handled correctly, which is what makes the bug easy to miss. ## Fix Dropping only the `/i` flag removes the lowercase-embedded false positives, but still mis-tags acronym/number-glued names such as `SVGAnimatedPath`, `RNAnimatedView`, and `MotionlessIndicator`. So the committed pattern anchors the token to a genuine PascalCase segment boundary: ```ts const ANIMATED_PATTERN = /(?<![A-Z0-9])(Animated|Animation|Transition|Motion)(?=[A-Z0-9_(.]|$)/; ``` - **Case-sensitive**, so a lowercase-embedded "motion" (`PromotionCard`, `Emotion`, `Locomotion`) never contains the capitalized token. - The leading `(?<![A-Z0-9])` rejects acronym/number-glued prefixes (`SVGAnimatedPath`, `RNAnimatedView`, `CMMotionManager`, `G2MotionSensor`) where the token is not a real PascalCase word-start. - The trailing `(?=[A-Z0-9_(.]|$)` requires the token to end a segment — another capitalized word, a digit/underscore, `(` or `.` (HOC/dotted display names like `Animated(View)`, `Animated.View`), or end-of-string — so it still matches real names while rejecting tokens that bleed into more lowercase (`MotionlessIndicator`). **Known limitation:** a bare `Motion` starting a PascalCase word (`MotionSensor`, `MotionManager`) still matches — it is structurally indistinguishable from a real animation name of the same shape (`MotionView`, and `@legendapp/motion`'s `Motion.View`) that we intend to tag. This over-tag is accepted collateral (it only excludes a component from perf findings); a hardcoded device-motion denylist would be more fragile than the rare false positive it removes. The behavior is documented in the code comment and pinned by a test. ## Tests `packages/tool-server/test/react-profiler-animated-pattern.test.ts` covers: - lowercase-embedded false positives (`PromotionCard`, `EmotionThemeCard`, `CommotionList`, `ProductCard`) → `isAnimated = false`, and `PromotionCard` reappears in `rank()` findings; - real animation components (`Animated`, `AnimatedView`, `MotionView`, `FadeTransition`, dotted/HOC forms) → `isAnimated = true`; - acronym-prefixed and digit-suffixed device-motion names (`CMMotionManager`, `G2MotionSensor`, …) → `isAnimated = false`; - the accepted bare-`Motion` device-name over-tag (`MotionSensor`, `MotionManager`, `MotionDetector`, `MotionTracker` → `isAnimated = true`), pinned so any future change is deliberate. The suite fails against the old `/i` regex and passes with the fix. `tsc --build` and ESLint on the changed files are clean.
8.6 KiB
8.6 KiB