chore(deps): bump vite-plus to v0.2.2#5
Draft
fengmk2 wants to merge 11 commits into
Draft
Conversation
…nco#1016) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…g helpers) (millionco#988) * fix(rules): shared FP-hardening infra (test harness + cross-cutting helpers) Foundation for the rule false-positive split off #986. Cross-cutting pieces every domain build/test depends on: - test-utils/attach-source-locations: attach `range` to AST nodes so eslint-scope-backed rules resolve correctly under the test harness. - constants/react: shared hook/name tables used by ~10 rule domains. - utils/contains-fetch-call, utils/build-same-file-memo-registry: shared detectors consumed by multiple domains. No changeset (intentional). * fix(rules): descend into synchronously invoked functions in containsFetchCall The stopAtFunctionBoundary walk pruned every nested function, so effects that kick off fetches via an async IIFE or a name-invoked inner function (`async function loadData(){...} loadData()`, `const loadData = async () => {...}; void loadData()`) were missed. Replace the blanket prune with a fixed-point walk that descends only into functions the body itself invokes, still skipping escaping callbacks like event handlers and returned cleanups. * fix(rules): drop `watch` from cleanup-returning subscription methods Returning a `watch` handle is not cleanup: react-hook-form's `form.watch(cb)` returns `{ unsubscribe }` (not callable) and `fs.watch` returns an FSWatcher needing `.close()`. Keep `listen`, whose returned disposer follows the `subscribe` contract, and pin the behavior with effect-needs-cleanup regression tests. * FP-FIX(a11y): eliminate false positives across accessibility rules (#989) * fix(a11y): eliminate false positives across accessibility rules Domain slice of the rule false-positive hardening split off #986: rule detector refinements + regression tests for this domain (and its domain-local utils/constants/fixtures). No changeset (intentional). * refactor(a11y): deslop FP-fix rules (reuse helpers, de-nest, relocate getImplicitRole) Behavior-preserving cleanup of the accessibility false-positive fixes: - interactive-supports-focus: replace the inline spread-attribute check with the existing `hasJsxSpreadAttribute` util (drops a byte-for-byte reimplementation and a now-dead `isNodeOfType` import). - no-redundant-roles: de-nest the implicit-role ternary into an if/else chain (AGENTS.md: no nested ternaries) and de-shadow the filter parameter. - prefer-tag-over-role: merge the two disjoint role sets that were only ever used together in one boolean union into one `ROLES_WITHOUT_CLEAN_TAG`. - role-supports-aria-props / no-redundant-roles: relocate `getImplicitRole` into `utils/get-implicit-role.ts`, removing the only rule-to-rule import in the a11y directory (shared helpers belong in utils/). - control-has-associated-label: un-glue and tighten a comment block. No behavior change: full oxlint-plugin suite (7380 tests) green; typecheck, lint, and format all clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(a11y): flag role={undefined} in no-noninteractive-element-interactions `collectRoleBranches` marked `null`/`false` literals as role-less but ignored the `undefined` Identifier, so `role={undefined}` — and ternary branches resolving to it — fell through the empty-branch early return and silenced the rule, a false negative on a genuinely role-less non-interactive element. Treat the `undefined` identifier like a `null`/`false` literal (`hasNonRoleBranch`), while leaving a genuinely opaque variable role (`role={dynamicRole}`) silent. Adds regression coverage for both. Addresses the Cursor Bugbot "Undefined role silences rule" finding on #989. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(a11y): treat spread children as content in objectHasAccessibleChild `objectHasAccessibleChild` counted an explicit `children` prop as content but not a `{...props}` spread, so `<h1 {...props} />` (forwardRef card titles, markdown component overrides) and `<a {...props} />` were flagged as empty. The RDE 500-repo run surfaced this as heading-has-content's dominant false positive (~83% of sampled hits, all `<h_ {...props} />`). Treat a JSX spread as possible children in the shared util — one fix covers heading-has-content, anchor-has-content, and alt-text's <object> check — matching the spread-bail pattern six sibling a11y rules already use. Genuinely empty elements (no spread) are still flagged; a11y suite green (3206), no OXC fixture divergence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(rules): treat dot-prefixed tool dirs (.dumi, .storybook) as non-production in isTestlikeFilename * fix(a11y): revert the ARIA-1.2 implicit-combobox upgrade in getImplicitRole (oxc parity) * fix(a11y): exempt <label> and testlike files, harden role-expression analysis in no-noninteractive-element-interactions * fix(a11y): drop the ref exemption in no-noninteractive-tabindex (keyboard handlers still exempt) * fix(a11y): treat native checked state as intrinsic aria-checked and skip custom components in role-has-required-aria-props * fix(a11y): count {" "} and static template children as anchor text, skip testlike files in anchor-has-content * fix(a11y): only display-none classes exempt the programmatic file input in control-has-associated-label --------- Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * FP-FIX(performance): eliminate false positives across perf/js-performance/bundle-size rules (#994) * fix(performance): eliminate false positives across perf/js-performance/bundle-size rules Domain slice of the rule false-positive hardening split off #986: rule detector refinements + regression tests for this domain (and its domain-local utils/constants/fixtures). No changeset (intentional). * fix(js-index-maps): don't treat nested-callback bindings as loop-varying collectLoopBoundNames walked the whole loop subtree, so a binding declared inside a nested callback could mark an outer loop-invariant .find() receiver of the same name as loop-variant and suppress the finding. Prune nested function scopes. (Bugbot) * fix(performance): tighten dynamic-import prefix + Intl memo write detection - no-dynamic-import-path: a relative prefix only counts as static when it has a real directory segment before the first hole. `./${pkg}/index.js` scopes the context to the whole dir and is flagged again; `./locales/${lang}.js` stays silent. - js-hoist-intl: drop `push` from the memo-write set — `array.push(new Intl…)` is unkeyed accumulation, not keyed reuse, so it's flagged again. (Bugbot) * fix(async-await-in-loop): treat return-inside-switch as a loop early exit loopBodyHasEarlyExit pruned whole switch subtrees so a `return` inside a switch (which still exits the loop) was missed, flagging order-dependent first-success loops. Split the walk: `return` prunes only nested functions; `break` still prunes nested loops/switches that capture it. (Bugbot) * fix(no-json-parse-stringify-clone): walk all enclosing functions for snapshot exemption isInsideSnapshotHelper stopped at the innermost function, so a deep clone inside a nested helper within a snapshot* function was wrongly flagged despite the persistence exemption. Walk outward through every enclosing function. (Bugbot) * fix(js-min-max-loop): direction-aware Math.min/max rewrite hint The comparator check accepted both ascending (a-b) and descending (b-a) sorts but always mapped [0]->min / [length-1]->max, inverting the suggestion for a descending sort. Return the sort direction and pick min/max from direction + index. (Bugbot) * fix(performance): fix RDE-caught FPs (cast receiver, replacer) + dedup rule helpers Two false positives surfaced by a 500-repo RDE eval (react-doctor caching disabled): - js-index-maps: `(x as T).find((i) => i.id === k)` on a loop-variant receiver behind a TS cast slipped past isLoopVariantReceiver because getRootIdentifierName didn't peel TSAsExpression. It now peels TS cast / non-null / paren wrappers (and ChainExpression) via stripParenExpression. - no-json-parse-stringify-clone: an inline function/array replacer transforms the output, so structuredClone is not an equivalent rewrite — those are now exempt (an identifier replacer still flags, preserving the existing contract test). Also consolidates duplicated guard helpers introduced across the perf rules onto existing shared utils — isFunctionLike / isInlineFunctionExpression, isEverySpecifierInlineType (promoted from rn-no-deep-imports into is-type-only-import), LOOP_TYPES, ITERATOR_PRODUCING_METHOD_NAMES — removes an unnecessary `as` cast, and trims over-long comments to match neighbor convention. Regression tests added for both FPs; full plugin suite green (7367 pass). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(changeset): patch changeset for perf-rules FP hardening Covers the perf / js-performance / bundle-size false-positive fixes in this PR (no changeset existed for the batch). Patch bump for oxlint-plugin-react-doctor; the fixed group cascades the rest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(harness): dispatch `${type}:exit` post-order and parse fixtures without ParenthesizedExpression Matches what oxlint compiles at runtime: every visitor gets enter/exit pairs (Program:exit special case removed) and `preserveParens: false` so paren-wrapped fixtures exercise the same AST rules see in production. Harness-parity regression tests pin the rules that depended on it. * fix(performance): precise early-exit and cancellation-guard detection in async rules async-await-in-loop: only an early exit conditioned on an awaited result (enclosing if/switch, or a preceding continue-guard clause like `if (!raw) continue; … return raw;`) marks the loop order-dependent; labeled breaks resolve to the loop they actually exit, and awaited-arg collection reuses collectReferenceIdentifierNames. async-defer-await: a bare `*Ref` identifier test no longer reads as a post-await staleness check — only an actual `.current` read counts. * fix(performance): correlate cache-memo arms in js-hoist-intl; dynamic flags in js-hoist-regexp js-hoist-intl: isInsideCacheMemo requires the `new Intl.*` to correlate with an actual cache read or write (lookup-initialized declarator, ??/|| with a lookup operand, ternary on a lookup test, if-guard that writes the cache, direct `.set`) instead of any enclosing memo-shaped expression. js-hoist-regexp: `new RegExp(pattern, flags)` with a non-constant flags argument is not loop-invariant, so don't flag it. * fix(performance): harden membership and iteration rules against RDE-caught FPs js-index-maps: skip loop-bound computed-index receivers; js-set-map-lookups: recognize single-character `includes` and indexOf-as-membership shapes (±1/0 comparisons behind wrappers); js-combine-iterations: exempt identity/Boolean `.filter` adjacencies (block-body identity included); js-min-max-loop: strip parens around comparator bodies so direction detection survives `(a, b) => (a - b)`; js-length-check-first: dominating length-guard detection handles ||-chains, inequality operators, and array reassignment between guard and comparison. * fix(performance): tighten cache and clone guard precision js-cache-property-access: written member-chain prefixes of any depth invalidate caching reads, `.length` reads are never cache-worthy, and shadowing parameters don't suppress outer-chain reports; js-cache-storage: inline iteration callbacks tally storage reads into the enclosing function instead of a fresh scope; js-tosorted-immutable: only a fresh allocation whose binding has no other reference exempts the `[...x].sort()` spread copy; no-json-parse-stringify-clone: the nearest named ancestor decides the snapshot exemption (React component names don't count) and inline revivers are exempt like replacers. * fix(performance): reduce render-rule FPs (memo comparators, hydration timing, memo-before-return) no-inline-prop-on-memo-component: only a default-equivalent custom comparator keeps the memo bailout relevant; no-usememo-simple-expression: paren-wrapped bodies and hook-call initializers are classified like their unwrapped forms; rendering-hydration-mismatch-time: time/random only counts when the enclosing function executes during render and test-like files are skipped; rerender-derived-state-from-hook: transitive consumer tracking so derivations feeding memoized values aren't flagged; rerender-memo-before-early-return: early returns that use ANY memoized value (including via parens/JSX) don't count as wasted memo work. * chore(changeset): note single-reference constraint on the tosorted spread exemption --------- Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * FP-FIX(architecture): eliminate false positives across architecture/correctness/design rules (#996) * fix(architecture): eliminate false positives across architecture/correctness/design rules Domain slice of the rule false-positive hardening split off #986: rule detector refinements + regression tests for this domain (and its domain-local utils/constants/fixtures). No changeset (intentional). * fix(no-many-boolean-props): exclude props.* wired as JSX event handlers The props-object path only skipped invoked callbacks (props.showMenu()); a boolean-prefixed prop wired as onClick={props.showMenu} was still counted, unlike the destructured path. Mirror the event-handler exclusion (Bugbot). * fix(no-render-in-render): scope render-prop exemption to props/this.props isRenderPropReceiver exempted any X.props.renderY() call; an unrelated object with a .props field could hide a real inline render* call. Require this.props (or the bare props identifier). (Bugbot) * refactor(architecture): consolidate event-handler-attribute predicate Deslop pass over the FP-hardening changes in this PR: - extract the `on*` event-handler-attribute check (duplicated twice in no-many-boolean-props) into a shared isEventHandlerAttribute type-guard util - move the memo(_, areEqual) pass-case test into the pass-cases describe block - add the changeset for this PR's false-positive reductions across the architecture/correctness/design rules (the foundation infra commit intentionally deferred it downstream) Behavior-preserving; full oxlint-plugin suite green (7375 tests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(no-uncontrolled-input): exempt disabled inputs (RDE false positive) RDE validation across 500 OSS repos surfaced 3 identical false positives: `<input value={x} disabled />` (supabase user-management's read-only email field, ported 3 ways). React suppresses its missing-`onChange` warning for `disabled` inputs just like `readOnly`, so a disabled value-input needs no handler and must not be flagged. - add `disabled` to VALUE_PARTNER_ATTRIBUTES - add no-uncontrolled-input.regressions.test.ts (disabled exempt, onInput exempt, genuinely-uncontrolled still flagged) Verified in the built bin against the real files at their scanned refs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(architecture): address bot review on FP-hardening rules Resolves Cursor Bugbot + Devin review findings on PR #996: - no-render-in-render: scope the render-prop parameter exemption to COMPONENT parameters, so a `render*` param of an ordinary nested helper is flagged again; exempt inline member calls on a nested prop bag (`props.slots.renderX()`) to match its already-exempt destructured form. - no-nested-component-definition: scope the rendered-JSX membership test to the candidate's own enclosing component (via isAstDescendant), so a sibling component's `<Inner/>` no longer falsely flags a same-named call-only helper in another parent. - no-outline-none: exclude the `focus:outline-none` / `focus:shadow-none` / `focus:ring-0` removal utilities from the focus-ring exemption; they strip focus styling rather than add a ring. - rendering-svg-precision: move MIN_DISTINCT_OVERPRECISE_SVG_TOKENS into constants/thresholds.ts per the magic-number convention. - extract a shared isComponentFunction util, deduped from the prop-stack tracker's private copy and reused by no-render-in-render. - drop the misplaced no-derived-useState "re-seeded draft buffer" test: it asserts an FP fix implemented in the state-and-effects PR (#990), not this architecture PR, so it failed here. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(architecture): scope-aware props resolution (bugbot re-review) Addresses two Cursor Bugbot findings from the re-review: - no-render-in-render: the `props` carve-out no longer matches by NAME. A local variable named `props` (`const props = { renderRow }`) is no longer treated as the component's props bag, so `props.renderRow()` on it is flagged again. Both `rootsInProps` and `tracesToPropOrParameter` now resolve the root through scope via `isComponentParameterSymbol`. - no-polymorphic-children: a body alias of the props (`const { children } = props`) is flagged again — it's the same smell as `({ children })` / `typeof props.children`. Resolution is component-aware, so `const { children } = node` (a non-prop parameter of a non-component tree walker) still stays quiet. Extracts the shared `isComponentParameterSymbol` util (component-aware parameter check) now used by both rules. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(rules): dispatch :exit visitors in the test harness, count call-argument callbacks as render evidence, treat .dumi as test-noise - run-rule.ts now dispatches `<NodeType>:exit` handlers like production oxlint, so stack-based rules pop between sibling declarations in tests. - functionContainsReactRenderOutput no longer treats function expressions passed directly as call arguments (`.map(item => <li/>)`, `useMemo(() => <div/>)`) as nested-render boundaries. - isTestlikeFilename marks `/.dumi/` docs-site paths as non-production. * fix(architecture): resolve fp-review findings across five architecture rules - no-many-boolean-props: callback exclusions are scope-aware (resolve to the component's own props binding), match renamed destructurings on the VALUE name, and extend to imperative-prefixed call arguments (`setTimeout(props.showMenu, 100)`). - no-nested-component-definition: nested components rendered by reference through a component prop (`component={Inner}`) are flagged too. - no-render-in-render: drop the blanket this.renderX() exemption (class fields are per-instance, so `this.` is not a stability signal) and extend the render-prop carve-out to plain/defaulted/conditional aliases of props-rooted render props. - prefer-module-scope-static-value: abstain when every reference is a read-only scalar lookup (`KEYS.includes(k)`); impure bare-call names only match unresolved globals or imports, not local helpers. - react-compiler-no-manual-memoization: a nullish memo comparator (`memo(Inner, undefined)`) is still redundant. * fix(correctness): resolve fp-review findings across correctness rules - html-no-invalid-paragraph-child / html-no-nested-interactive: the explicit `children` prop is a real DOM child, so it no longer stops the ancestor walk at the attribute boundary. - no-prevent-default: an anchor stays flagged unless the handler carries positive navigation evidence (router/window calls, navigate-shaped names, prop-handler delegation) — analytics-only handlers are still dead links; tag the rule test-noise for demo/test files. - no-uncontrolled-input: a literal `disabled={false}` no longer excuses a missing onChange; tag the rule test-noise. - rendering-svg-precision: count over-precise token OCCURRENCES rather than distinct tokens (Inkscape uniform-scale matrices repeat one factor), tag the rule test-noise, and add regression coverage. * fix(design): resolve fp-review findings across design rules - no-gray-on-colored-background: variant scopes are order-insensitive and !important-aware; base utilities pair with variant-scoped counterparts when the variant carries no same-property override; include the 950 gray shade. - no-layout-transition-inline: match an exact layout-property token set (adds border-*-width, line-height, column-width) so lookalikes like stroke-width stay silent. - no-long-transition-duration: the infinite exemption is per shorthand segment (an animation NAME containing 'infinite' still counts) and decorative aria-hidden elements are exempt. - no-outline-none: only utilities that ADD a visible ring on the element's OWN focus count as a replacement indicator; conditional tabIndex qualifies only when both branches are negative. - no-side-tab-border: the side-scoped border color decides before the base color; parse-color-to-rgb learns hsl() and Tailwind underscore spacing. * chore(changeset): sync fp-fix changeset with final rule behavior --------- Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * FP-FIX(security): eliminate false positives across security + security-scan rules (#993) * fix(security): eliminate false positives across security + security-scan rules Domain slice of the rule false-positive hardening split off #986: rule detector refinements + regression tests for this domain (and its domain-local utils/constants/fixtures). No changeset (intentional). * refactor(security): deslop command-exec, metadata-secret, postmessage rules Behavior-preserving cleanup of the FP-hardening detectors: - command-execution-input-risk: split the two-branch `(?:…)|(?:…)` alternation into scanByPattern's array-of-patterns form (the documented idiom, matching raw-sql-injection-risk) so each taint model reads as a discrete pattern. - package-metadata-secret: drop the fragile regex `.source` string-equality filter for `!pattern.test("service_role")` — robust to a re-spelling or flag change of the source pattern in security.ts. - postmessage-origin-risk: inline a single-use local. No behavior change: matching is byte-identical (281 security + security-scan tests pass; typecheck/lint/format clean). No changeset — behavior-preserving, and this split branch ships no changeset by design. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(security): catch leaked JWT credentials in package metadata Dropping the bare service_role keyword from package-metadata-secret must not drop the credential itself: add JWT_LITERAL_VALUE_PATTERN (header AND payload segments are base64url JSON, so both start with eyJ) and append it to PACKAGE_METADATA_VALUE_PATTERNS only — in source files anon-key JWTs are legitimate, but ANY JWT committed into package.json is a leak. * fix(security): tighten spawn/shell taint detection in command-execution-input-risk Recompose the patterns from named String.raw sources and split the spawn branch into three precise shapes: tainted first argument, fixed shell binary running tainted input via its command flag, and shell:true with request taint anywhere in the call (order-independent). Zero-taint spawn/exec with shell:true and a fixed argv no longer fires; the python shell=True kwarg keeps firing on the exec branch. * fix(security): walk every concat operand in raw-sql-injection-risk Replace the single-operand escaper exemption with a safe-tail regex: after the leading literal, zero or more safe operands (string literal or SQL escaper call) followed by an unsafe one fires. One escaped operand can no longer launder a later raw concatenation, and HTML escapers like _.escape()/validator.escape() are no longer treated as SQL-safe; escapeLiteral/escapeIdentifier and multi-line/parenthesized escaper operands stay exempt. * fix(security): cover ancestor and arrow-prop filter shapes in svg-filter-clickjacking-risk Three alternatives: the same-tag window now tolerates arrow props (=> consumed as a unit, bare > still bounds the tag), an unquoted filter:url(# before the iframe catches wrapper/ancestor filters, and the <fe…> primitive window widens to 700 chars. The mined sibling-after- the-iframe decorative-filter FP stays silent. * fix(security): catch concat-built role params and string-safe firebase windows clickjacking-redirect-risk: move [?&](?:amp;)?role= outside the \b group so concat-built and entity-encoded role URLs match (a quote before ? has no word boundary); the ARIA role FP guard stays silent. firebase-client-owned-authz-field: make the statement window quoted- string-aware so a ; inside a string literal in the write's own args no longer truncates it before the authz field. * fix(security): treat #fragment credentials as credentialed URLs in no-secrets-in-client-code Widen the CREDENTIALED_URL_PATTERN delimiter class [?&] -> [?&#] so a fragment-carried credential (OAuth implicit-flow #access_token=) defeats the public-URL exemption and still flags. * fix(secret-in-fallback): only exempt env names public by construction A PUBLIC/PUBLISHABLE/ANON segment anywhere in the name no longer skips the rule: the exemption now requires a leading framework public prefix (NEXT_PUBLIC_/EXPO_PUBLIC_/GATSBY_PUBLIC_/NUXT_PUBLIC_/REACT_APP_PUBLIC_/ VITE_PUBLIC_/bare PUBLIC_) or a publishable/anon key ending (...PUBLISHABLE_KEY/...ANON_KEY), and never applies to names ending in _SECRET/_PRIVATE_KEY/_PASSWORD/_PASSWD. INTERNAL_PUBLIC_WEBHOOK_SECRET with a hardcoded fallback flags again; NEXT_PUBLIC_*, STRIPE_PUBLISHABLE_KEY, and SUPABASE_ANON_KEY fallbacks stay silent. --------- Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * FP-FIX(react-native): eliminate false positives across react-native rules (#992) * fix(react-native): eliminate false positives across react-native rules Domain slice of the rule false-positive hardening split off #986: rule detector refinements + regression tests for this domain (and its domain-local utils/constants/fixtures). No changeset (intentional). * fix(react-native): inline type imports + literal-flip scroll latch - rn-no-legacy-expo-packages / rn-no-non-native-navigator: skip fully inline-type imports (`import { type Foo }`), not just `import type`, via the shared isTypeOnlyImport helper — they erase to no runtime code. Mixed type+value imports still flag. - rn-no-scroll-state: a set-once latch must write a literal constant; a guard that reads the same state but writes a changing value (`if (offset !== last) setLast(offset)`) is a per-frame sync and stays reported. (Bugbot) * fix(rn-no-falsy-and-render): scope-prune nested useState shadowing isBooleanUseStateName walked the whole enclosing scope, so a nested component's useState(false) of the same name could mask an outer useState(0) gate and hide a real bare-0 render crash. Don't descend into nested function scopes. (Bugbot) * refactor(react-native): consolidate type-only-import checks, reuse isHookCall Route all six react-native import rules (bottom-sheet, deprecated-modules, prefer-expo-image, prefer-pressable, prefer-reanimated, no-panresponder) through the shared isTypeOnlyImport helper instead of re-implementing the importKind / every-specifier check inline, and delegate rn-no-falsy-and-render's isUseStateCall to the existing isHookCall. Drop the seven near-duplicate "type-only imports are erased" comments now that the helper's doc is the single source of truth. Behavior-preserving: verified byte-identical over adversarial fixtures and the 283 react-native rule tests are unchanged. Net -39 LOC. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(rn-list-data-mapped): flag aliased recycler imports The rule gated on `REACT_NATIVE_LIST_COMPONENTS.has(localName)`, so an aliased recycler (`import { FlashList as FL } from "@shopify/flash-list"`) resolved to `FL`, missed the set, and returned before the provenance check ever ran — a false negative its two sibling list rules already handled. Extract the recycler-resolution pattern (duplicated across all three list rules) into a shared `resolveImportedRecyclerName` helper that maps a local JSX name back to its canonical export via a real import, covering aliases. rn-list-data-mapped now resolves recyclers by provenance and restricts the built-in branch to the true built-in lists (FlatList/SectionList/ VirtualizedList), so an ambient un-imported recycler still never fires. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(utils): binding-provenance helpers + inline-type-import superset * fix(react-native): resolve real list and Dimensions bindings through aliases, namespaces, and requires * fix(react-native): tighten latch, static-value, and list-item detectors * fix(react-native): recognize namespace member aliases as RN bindings `const FlatList = RN.FlatList` / `const Dimensions = ReactNative.Dimensions` (where RN is a react-native namespace import) were misclassified as local rebindings, silencing rn-list-data-mapped and rn-no-dimensions-get. Extract the shared provenance check into getInitializerModuleSource — require call (member-unwrapped) or namespace-import-rooted reference — and route both rules through it. --------- Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * FP-FIX(frameworks): eliminate false positives across nextjs/server/tanstack/jotai/preact rules (#995) * fix(frameworks): eliminate false positives across nextjs/server/tanstack/jotai/preact rules Domain slice of the rule false-positive hardening split off #986: rule detector refinements + regression tests for this domain (and its domain-local utils/constants/fixtures). No changeset (intentional). * fix(redirect-in-try-catch): require a real re-throw of the caught error A catch only forwards a Next.js/TanStack redirect's control-flow error when it re-throws the CAUGHT binding (throw e). Previously: - nextjs: any throw in the catch suppressed (so throw new Error() — which swallows the redirect — was missed). - tanstack-start: a bare isRedirect()/isNotFound() call suppressed even with no rethrow. Both now require throw <caughtBinding>; fresh throws / guard-only catches flag. (Bugbot) * refactor(rules): consolidate duplicated framework-rule helpers into shared utils The false-positive hardening pass copy-pasted the same helpers across many rules. Extract four shared utils — find-enclosing-function, get-function-binding-name, collect-handler-referenced-names, catch-clause-rethrows-caught — plus a HOOK_NAME_PATTERN constant, and repoint every rule at them. Also reuse existing utils (isFunctionLike, getCalleeName, findJsxAttribute) in place of re-implemented inline copies, and drop a nested ternary. Behavior-preserving: the full plugin suite is unchanged (7409 passing, 88 skipped); typecheck, lint, and format are clean. Net ~-250 source lines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(rules): close two FP patterns found by a 500-repo eval run RDE validation (500 distinct OSS repos, cache disabled, 161 hits manually classified) surfaced two systematic false positives: - server-hoist-static-io flagged reads whose path derives from a handler param through intermediate bindings (params -> pathArray -> filePath -> fullPath). Taint now propagates through variable declarations, mirroring tanstack-start-loader-parallel-fetch. - query-mutation-missing-invalidation missed tRPC-style invalidation (`utils.posts.invalidate()`). `invalidate` joins QUERY_CACHE_UPDATE_METHODS. Adds a changeset for the branch's framework-rule FP hardening. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(query-destructure-result): only real forwarding suppresses, not any mention Bugbot: isForwardedBinding treated ANY non-member-access reference as "forwarded", so an effect dependency array ([query]) or a stray mention in a nested closure silenced the rule while the component read query.data field-by-field in render. Forwarding is now a positive list matching the escape's documented intent: returned (incl. implicit return and returned tuple/object), call argument, JSX, spread, or re-bound. A bare dependency- array mention no longer suppresses. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tanstack-start-redirect-in-try-catch): try/finally and finally-clause throws are not swallowed Bugbot: findEnclosingTryForThrow treated ANY enclosing TryStatement as swallowing. A `throw redirect()` in a bare try/finally (no catch) or inside a finally clause propagates normally, so neither must be flagged. The nextjs sibling already had the correct walk (try BLOCK contains the node + a catch handler exists, keep climbing past catch/finally so an outer swallowing try is still found) — extract it as the shared findGuardingTryStatement util and use it in both rules. Also fixes the inner-catch false negative: a throw in an inner catch swallowed by an OUTER try/catch is now reported. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(rules): shared helpers follow effect-invoked functions and transparent try/catch * fix(nextjs): resolve real next/navigation bindings and effect-run control flow before flagging * fix(server): only flag module state that is actually mutated and follow request-path bindings * fix(tanstack-query): verify query/mutation receiver bindings through scope analysis * fix(tanstack-start): follow loader/server-fn control flow and validator shapes before flagging * fix(jotai): scope-aware atom and query-envelope detection in select-atom and raw-query-atom * fix(preact-no-children-length): require component evidence before treating children as VNodes * fix(no-document-start-view-transition): only fire in files importing React's ViewTransition * fix(client-passive-event-listeners): trace assigned and member-expression handlers for preventDefault * docs(changeset): describe the full framework FP-hardening surface --------- Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * FP-FIX(state-and-effects): eliminate false positives across state/effect rules (#990) * fix(state-and-effects): eliminate false positives across state/effect rules Domain slice of the rule false-positive hardening split off #986: rule detector refinements + regression tests for this domain (and its domain-local utils/constants/fixtures). No changeset (intentional). * fix(no-direct-state-mutation): recognize lazy useState object/array initializers The plain-state gate only matched a direct ObjectExpression/ArrayExpression initializer; lazy initializers (useState(() => []), useState(() => ({}))) were excluded, so in-place mutations of that render state went unreported. Resolve the lazy initializer's returned literal too (Bugbot). * fix(rules): harden the shared guards behind the state/effect FP fixes - reads-post-mount-value: member/global post-mount reads split into reusable predicates; wider imperative-source coverage - contains-non-deterministic-source: don't descend into stored callbacks - is-result-discarded-call: discarded compound positions (guards, statement ternaries, sequences, concise arrow bodies) - is-namespaced-api-call: match the base receiver identifier on member chains (destructured router.replace(...) et al) - is-testlike-filename: match dot-directory tooling surfaces (/.dumi/, /.storybook/) against the full path, before the source-root cut - data-sink-method-names: split STRING_READ_METHOD_NAMES out so callers can special-case props-object string-read collisions - new is-controlled-prop-mirror: setter wired into a JSX event-handler attribute + bare-prop re-sync (the controlled/uncontrolled mirror) * fix(state-and-effects): stop flagging data sinks and discarded reads in the pass-to-parent rules no-pass-data-to-parent: a namespaced API receiver (router.replace(...)) is not a parent callback, but a string-read name called directly ON the props object (props.search(results)) is — un-exempt that collision. no-pass-live-state-to-parent: recognize the widened discarded-result shapes so guarded/ternary/concise-arrow notifications still count as fire-and-forget hand-backs. * fix(state-and-effects): skip controlled-prop mirrors and post-mount reads in the derived-state family A useState seeded from a prop whose setter is wired into a JSX event handler is a controlled/uncontrolled value mirror holding the user's live edits — not a render-derivable value (no-derived-state, no-derived-state-effect, no-derived-use-state). A value measured off a ref or read from a browser global after mount can't be computed during render, so effects that adjust state from it stay silent (no-adjust-state-on-prop-change). * fix(no-cascading-set-state): walk stored handlers, model early-return guard exclusivity Inverted the function-walk skip: only INLINE callbacks handed to non-sync-iteration callees (subscribe/then/setTimeout) are deferred; variable-stored helpers and listener handlers are walked again — their call sites are the writes the reducer recommendation targets (cookiekit bench). Statement sequences now treat an early-returning guard branch as mutually exclusive with the post-guard body, and switch runs sum fall-through cases. * fix(state-and-effects): suppress externally-driven state in the effect-origin rules State written exclusively by a timer / listener / observer / subscription (or seeded from a post-mount read) has no React handler to fold into and no render-time value to derive, so no-initialize-state, no-event-handler, no-prop-callback-in-effect, and no-chain-state-updates stay silent for it while keeping handler-driven state flagged. * fix(state-and-effects): rerender-rule FP hardening rerender-functional-setstate: spread-merge setters are flagged only in deferred-execution contexts (setTimeout / .then / listeners / debounce) where the closure outlives later renders; sync render-path handlers close over fresh state. Arithmetic reads in sync click handlers still fire (batched double-clicks lose updates). rerender-lazy-state-init: skip initializers that read post-mount values. rerender-state-only-in- handlers: drop refs driven exclusively by imperative browser events while keeping the other tested props/state reported. * fix(advanced-event-handler-refs): scope-aware stable-handler resolution Replace the name-based block scan with the scope-aware findVariableInitializer (a prop param shadowing an outer stable binding now resolves to the param). Treat the useEvent-family hooks and empty-deps useMemo as stable handler identities, and exempt a useRef-backed subscription receiver from the re-subscription bailout. * fix(rules): mutation, selector, and uncontrolled-input FPs no-direct-state-mutation: sharpen the plain-state boundary between React-managed data and opaque third-party instances (method chains on plain data stay plain). redux-useselector-inline-derivation: stop flagging selectors whose derivation is the store's own memoized shape. no-uncontrolled-input: skip mined testlike shapes and static inputs that never carry user state. * test(react-doctor): re-pin the state-rule e2e regressions to the hardened detectors external-state-origin: the deferred-suppression case is now an inline subscription callback (stored listener handlers are counted by design — cookiekit bench), with a new true-positive pin for the stored-listener fan-out. no-initialize-state-post-mount and no-uncontrolled-input pick up the widened post-mount and testlike discriminators. * FP-FIX(react-builtins): eliminate false positives across builtin DOM/JSX rules (#991) * fix(react-builtins): eliminate false positives across builtin DOM/JSX rules Domain slice of the rule false-positive hardening split off #986: rule detector refinements + regression tests for this domain (and its domain-local utils/constants/fixtures). No changeset (intentional). * fix(button-has-type): mirror JSX spread bailout + quoted type-prop forward (createElement) - createElement now bails on a spread-only / opaque props bag (`{ ...props }`, `createElement("button", props)`) the same way the JSX arm bails on a spread, since the forwarded object may supply `type` at runtime. null / absent props still report missing. - bindsToDestructuredTypeProp recognizes a quoted `{ "type": kind }` key as a consumer forward, matching the bare-identifier key. (Bugbot) * fix(button-has-type): report missing type for nullish createElement props undefined / void 0 props carry no type, like an explicit null, so they must report missing rather than be treated as an opaque (possibly type-forwarding) props bag. (Bugbot follow-up) * refactor(react-builtins): deslop FP-hardening without changing behavior Simplify the recently added false-positive guards while preserving every regression-tested behavior (plugin suite unchanged: 7357 pass / 91 skip). - Extract the re-inlined `null | undefined` check into one shared `utils/is-nullish-expression.ts` and repoint `button-has-type` (`isNullishPropsArgument`, keeping its local `void 0` case) and `is-meaningful-jsx-child`, removing the triplicated logic. - button-has-type: unscramble the comment stack so each rationale sits above the function it describes. - no-unstable-nested-components: drop the redundant `reportNode` param from `enqueueCandidate` (every call site passed the candidate twice). - void-dom-elements-no-children: `.some(isMeaningfulJsxChild)` — drop a gratuitous `as EsTreeNode` cast, the wrapper arrow, and the dead import. - no-find-dom-node: inline the single-use `REACT_DOM_MODULE` constant. - exhaustive-deps / dom-property-tags: trim comments that restated themselves or the file header. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(changeset): add patch changeset for react-builtins false-positive fixes The FP-hardening changes published rule behavior in oxlint-plugin-react-doctor but the branch shipped without a changeset; add one so the fix is released. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(iframe-missing-sandbox): mirror the spread/opaque-props bailout in createElement The JSX path already bails on a spread (`<iframe {...props} />`) since sandbox can be forwarded at runtime, but the `createElement` path still reported a missing sandbox for an opaque props bag (`createElement("iframe", props)`) and for `createElement("iframe", { ...props })`. Mirror the JSX bailout — and the identical handling in `button-has-type` — so those cases no longer false-positive, while `createElement("iframe", null)` and an explicit object without a spread or `sandbox` still report. Uses the shared `isNullishExpression` util. (Cursor Bugbot #991.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(void-dom-elements-no-children): ignore nullish positional children in createElement RDE (500-repo sweep) surfaced `React.createElement("img", attr, null)` — the idiomatic "no children" form — being falsely flagged: the createElement path counted any positional arg via `arguments.slice(2).length > 0`, so a `null` / `undefined` / `void 0` child triggered the diagnostic. Mirror the JSX path's isMeaningfulJsxChild (and the sibling iframe createElement bailout) by filtering nullish positional children before deciding. A real positional child still fires. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(react-builtins): resolve all PR #991 review-thread findings Bugbot: - no-unstable-nested-components / no-call-component-as-function: the instantiation gates are now keyed by the BINDING IDENTIFIER node the usage resolves to (via scopes.symbolFor(...).bindingIdentifier), not by name, so a same-named JSX usage of a different binding (shadowed import, name collision) no longer counts. The binding node — not symbol.id — is the key because scope analysis registers a hoisted declaration under two symbol records that share one binding identifier. For a named function expression the declarator id wins over the inner `.id` (outside references resolve to the variable). - no-call-component-as-function: `createElement(Name, …)` now counts as an instantiation alongside `<Name/>`. - rules-of-hooks: the multi-hook render-scope escape now also covers the React 19 `use()` branch, so `use(...)` in a `create*` factory that issues several hook calls is no longer reported as non-component. Devin: - no-danger-with-children: the createElement path filters nullish positional children (`…, null)`), mirroring the JSX path. - isNullishExpression now includes the `void` UnaryExpression case — every caller added it manually, and `{void 0}` renders exactly like `{undefined}` — deleting the three per-rule void checks and fixing the JSX/createElement asymmetry. - react-native collect-text-wrapper-components: local isMeaningfulJsxChild renamed to isNonWhitespaceJsxChild (same name as the shared util but deliberately different semantics; rename only). Regression tests added for each; plugin suite 7373 pass / 91 skip. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(react-builtins): count callback JSX as render-output evidence for the enclosing function Only name-bound function expressions (nested component definitions) are render-evidence boundaries now; JSX inside call-arg callbacks (rows.map(row => <tr/>)) and returned closures flows into the outer function's render, so it counts as evidence again. * fix(react-builtins): resolve dumi-docs mined false positives - treat /.dumi/ doc trees as non-production files (checked against the full path, before the source-root slice) - allow transform-origin on a/defs/gradients/stop SVG elements - recognize indicator/decoration/*Children as slot props in jsx-no-jsx-as-prop * fix(iframe-missing-sandbox): narrow the spread bailout to iframes without an explicit src An explicit src marks the element as the real embed site, so a missing sandbox alongside a spread is the author's omission and is reported again (JSX and createElement paths). Also skip non-production files. * fix(rules-of-hooks): tighten the render-scope escape and local non-hook callees - gate the structural render-scope escape on factory-shaped names (init/create*/make*/build*) with no enclosing component or hook, so an arbitrary helper with two copy-pasted hooks no longer qualifies - a use-prefixed callee resolving to a local hook-free function (e.g. ajv's useKeyword) is not treated as a React hook on the non-component report paths * fix(no-unstable-nested-components): count escaping reads and member-expression instantiations A nested component consumed by reference (withAnalytics(Inner), component={Inner}, object/array/return/assignment values) escapes its declaration site, and <Thing.Panel/> / createElement(sections.General) instantiate member-assigned candidates — all now count as instantiation evidence. A direct call (Inner()) still does not. * fix(no-prevent-default): exempt href-less anchors and handlers that navigate An <a> without href never navigates on click (anchor-as-button), and an anchor whose handler performs its own navigation after preventDefault() (router push, location.href assignment, window.open, platform link openers) is custom SPA navigation — neither is a dead link. Handlers that only log or track after preventDefault() are still flagged; the <form> path is untouched. * fix(exhaustive-deps): harden accessor-call dependency handling - a computed callee (items[index]()) stays a complex dependency instead of collapsing to its root name and silently matching the capture - unstable-function-dep symbol lookups resolve through the callee for accessor-call deps, so getConfig() finds its binding - an unused zero-arg call dep (Date.now()) is reported as a complex expression instead of a callee-keyed unnecessary-dep message * fix(react-builtins): four rule-local point fixes - button-has-type: identifier resolution is proof only through an unconditional const initializer, and a destructured type key is a consumer forward only when the pattern roots at a function parameter - jsx-no-comment-textnodes: a // separator line continuing a preceding {expression} ({used} // 512 GB) is rendered text, not a comment - no-danger-with-children: two or more surviving children form an array that trips React's props.children != null guard even when every entry is nullish (JSX and createElement paths) - no-call-component-as-function: a nested helper that owns hook calls is not exempt — calling it inlines its hooks into the caller's order * chore(changeset): describe the fp-review hardening round * fix(react-builtins): only count render-flowing reads as nested-component instantiation A PascalCase escaping read now counts as instantiation evidence only when its value flows into a render-shaped sink (JSX expression container, createElement/cloneElement argument, return value, or a PascalCase binding a consumer can render). Arguments to non-rendering calls whose result is discarded (track(Inner), console.log(Inner)) no longer resurrect an inline-only helper. * fix(react-builtins): exclude local non-hook use* callees from the render-scope hook count countOwnScopeHookCalls now applies the same isLocalNonHookFunctionCallee exclusion the report paths use, so a create*-factory with one real hook plus one local useKeyword(...) codegen-helper call no longer reaches the render-scope threshold and wrongly exempts the real hook. A shared visited set guards the mutual recursion between the two helpers. * chore(react-builtins): drop unused Rule type import from rules-of-hooks * fix(react-builtins): unify nearestEnclosingFunction callers onto findEnclosingFunction after foundation merge * fix(no-prevent-default): keep spread anchors checked since a spread can forward a real href * fix(no-prevent-default): require a global receiver for location.href navigation evidence * fix(jsx-no-comment-textnodes): only treat digit-leading text after an expression as a separator --------- Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: resolve PR #988 bugbot findings across four rules - no-pass-live-state-to-parent: port the props.search() string-read carve-out from no-pass-data-to-parent (shared isWholePropsObjectReference helper) - no-render-in-render: exempt render props called through props aliases (const slots = props.slots) with cycle-safe symbol tracing - no-noninteractive-element-interactions: opaque role branches no longer count toward the always-interactive proof; truthy string-literal || left short-circuits - effect-needs-cleanup: .listen() only counts as disposer-returning in the callback-argument shape (Node server.listen(port) returns the server) --------- Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lionco#1012) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com> Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com>
…Ink TUI (millionco#979) (millionco#1017) * fix(no-derived-state): stop flagging accumulators grown through functional updaters Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix(no-array-index-as-key): allow index keys on string-derived character arrays Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix(prefer-useReducer): require a co-update signal and correct the batching claim Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix(jsx-no-jsx-as-prop): use conditional wording when the receiver's memoization is unknown Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * chore: changeset for ink-TUI false-positive fixes Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * refactor(prefer-useReducer): reuse collectUseStateBindings for setter names Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * refactor(rules): drop unneeded casts and nested ternaries flagged by ship review Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix(no-array-index-as-key): follow local bindings to string-derived receivers A 500-repo eval found the string-derived exemption missing the common `const parts = line.split(urlRegex); parts.map(...)` shape (openreplay, outline) — the receiver is an identifier, not the split call itself. Follow the binding to its initializer, bounded by the existing type- resolution depth limit. Also dedupe the "Array.from whose first argument is provably a string" predicate that existed twice, and correct the doc comment: split produces positional fragments (characters, lines, tokens), not always one entry per character. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(react-builtins): stop classifying lazy() as memoising React.lazy defers loading but does not skip re-renders, so treating it like memo() made jsx-no-jsx-as-prop assert a memo bailout that does not exist (3 of 5 assertive messages in a 500-repo eval sat on lazy receivers) and made the memoised-gated rules (jsx-no-new-object/array/ function-as-prop, prefer-stable-empty-fallback) report fresh-reference props to components with no bailout to defeat. lazy receivers now resolve "unknown": conditional wording, and the gated rules stay quiet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore: update changeset for the eval-driven fixes Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…N rules (millionco#1013) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com> Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com>
…and workflows (millionco#1015) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com> Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com>
Co-authored-by: Aiden Bai <aiden.bai05@gmail.com> Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com>
…millionco#1020) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
📦 GitHub Action release recommendedThis PR changes the React Doctor GitHub Action's release surface:
The composite action is versioned independently from the npm packages, so it After merging, cut the tag from the merge commit on git checkout main && git pull --ff-only
merge_commit=$(git rev-parse HEAD)
git tag -a v0.0.1 "$merge_commit" -m "react-doctor action v0.0.1"
git tag -fa v0 "$merge_commit" -m "react-doctor action v0 (floating major -> v0.0.1)"
git push origin v0.0.1
git push --force origin v0 # moves only the floating major pointerThis bump can also be performed automatically on merge — set the repo |
commit: |
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.
Summary
Bump
vite-plusand related packages to the pkg.pr.new prerelease build for v0.2.2 (registry-bridge commit build) to smoke-test the prerelease.vite-plus+vite(alias to@voidzero-dev/vite-plus-core) andvitestpinned to the commit build across deps / overrides / catalogsminimumReleaseAgeenabled with thevite-plus/@voidzero-dev/*/ oxc / oxlint stack excluded.npmrc(or.yarnrc.yml) points the package manager at the registry bridge (prerelease scaffolding)Test plan