-
-
Notifications
You must be signed in to change notification settings - Fork 737
feat(transformer): Support nested member expressions in React Fast Refresh #16577
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…fresh Add support for detecting hooks called via nested member expressions like `FancyHook.property.useNestedThing()` in React Fast Refresh. Previously, only direct hook calls and single-level member expressions were supported. This caused nested member expression hooks to force a full reset on HMR instead of preserving state. This implementation matches React PR #35318: facebook/react#35318 Co-authored-by: Dunqing <[email protected]>
…essions Refactor to use recursive helper function that handles arbitrary nesting depth (e.g., A.B.C.D.useHook) instead of just 2 levels. Also update test expectation for unbound reference case to correctly reflect force_reset behavior. Co-authored-by: Dunqing <[email protected]>
...ugin-transform-react-jsx/test/fixtures/refresh/nested-member-expression-with-hooks/output.js
Show resolved
Hide resolved
CodSpeed Performance ReportMerging #16577 will degrade performances by 4.23%Comparing Summary
Benchmarks breakdown
Footnotes
|
|
@copilot CI fails, please rebase and update snapshots. |
I first noticed that `parse_literal_type_node` was always called with `negative` = `false`. Then I split function `parse_rest_of_literal_type_node` into the more specific functions `parse_literal_type` and `parse_literal_type_negative` and inlined code for parsing `Kind::NoSubstitutionTemplate`. This avoids some redundant checks, makes code simpler and leads to nine lines less code.
Pure refactoring.
- Read raw config JSON in CLI side - We used to use `Oxfmtrc::from_file()`, but we don't now - I will refactor `Oxfmtrc` related things later - Then pass it to Prettier This means: - Config values are now applied to non-JS formatting - Plugins are partially supported - Like `prettier-plugin-packagejson` - Which targets non-JS and overrides builtin parser behaviors and if it was written in ESM Lastly, I will update this config with our defaults (e.g. add `printWidth: 100` if not specified in raw config) in next PR.
Fixes #16530 - Populate raw JSON config with parsed `FormatOptions` If there is one concern, it is how to handle values currently supported only by `oxc_formatter`, such as `objectWrap: always`. 🤔 Now it will fall back to `preserve`, which produces the intended result rather than `collapse`. However, this falls into the same category as the issue where `oxc_formatter` is not adapted for JS-in-XXX part.
- Pass `filepath` to Prettier Doing this means that plugins that depend on `filepath` now work.
…nt nodes (#16585) Refactor `AssignmentLike` formatting for handling left-hand-side node-only cases. Remove `AssignmentLayout::OnlyLeft` layout, as it is useless; once a node only has a left-hand side, we should print left and return early as soon as possible to avoid unnecessary operations for the right-hand side. Has a slight performance improvement <img width="1382" height="545" alt="image" src="https://github.com/user-attachments/assets/23de34bf-6238-43bb-ad86-3ef13242a682" />
…perty to be the same as other assignment-like nodes (#16588) Align the formatting logic of `BindingProperty` to be the same as Prettier. In Prettier, both `BindingProperty` and `ObjectProperty` are referred to as `ObjectProperty`. The performance improved because the elements were reduced a little bit and avoided always using the following formatting logic to print the right-hand side of the `BindingProperty`, since `indent_if_group_breaks` is an expensive element. ```rs write!( f, [ ":", group(&indent(&soft_line_break_or_space())).with_group_id(Some(group_id)), line_suffix_boundary(), indent_if_group_breaks(&self.value(), group_id) ] ); ``` <img width="1382" height="545" alt="image" src="https://github.com/user-attachments/assets/cd174578-6b4e-441c-8adf-600346ec7935" />
…markdownDescription fields to JSON Schema (#16587) We should probably also improve the `type: string` stuff in the output Markdown to serialize enums with their actual values, but that's a separate problem. This also updates the logic for generating the oxfmtrc `configuration_schema.json` file so it properly matches the way we generate the configuration_schema.json for oxlint, including with `markdownDescription` fields. See the oxlintrc file [here](https://github.com/oxc-project/oxc/blob/09ca3864227b30fa271d0ff35c5b5aa657f7c575/crates/oxc_linter/src/config/oxlintrc.rs#L205). Before: <img width="633" height="417" alt="Screenshot 2025-12-07 at 10 29 13 PM" src="https://github.com/user-attachments/assets/5cb205e3-2180-445b-a255-10b0831ff38a" /> After: <img width="807" height="213" alt="Screenshot 2025-12-07 at 10 30 07 PM" src="https://github.com/user-attachments/assets/f5b1eb5b-bcb9-4348-8517-12ef3b91b155" />
Updates submodule dependencies to their latest commits. ## Changes - test262: `d0994d6` → `c0cf527` - babel: `7958603` → `3591b24` - TypeScript: `669c25c` → `c21f73f` - estree-conformance: `3e67aec` → `1f2816b` This PR is automatically generated by the [update_submodules workflow](https://github.com/oxc-project/oxc/blob/main/.github/workflows/update_submodules.yml). Co-authored-by: graphite-app <[email protected]>
…options()` (#16678) - Update `into_format_options()` to `into_options()` - Now it returns `FormatOptions` and `OxfmtOptions` - Apply changes - Also make all `Oxfmtrc` fields as `Option` to distinguish undefined and default - Update doc comments
|
@copilot, Your previous work is good, but please restart from scratch, as your PR includes loads of commits from main. 😅 |
…e found (#16676) In short, this PR fixes #16655 Input: ```js // THIS IS A GENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. import { apiClient } from "../../apiClient"; import { useMutation, UseMutationOptions } from "@tanstack/react-query"; ``` 🆖 Before fix: Comment is attached to `import { apiClient` line. ```js import { useMutation, UseMutationOptions } from "@tanstack/react-query"; // THIS IS A GENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. import { apiClient } from "../../apiClient"; ``` 🆗 After fix: Comment with empty line is not attached. ```js // THIS IS A GENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. import { useMutation, UseMutationOptions } from "@tanstack/react-query"; import { apiClient } from "../../apiClient"; ``` However, the implementation itself was not straightforward; it required a concept to represent `OrphanContent`.
just moving some files around :)
…#16688) Add `parserOptions.lang` to `RuleTester`, as a more direct way to set language of code than setting filename. Accepted values for `lang`: `"js"`, `"jsx"`, `"ts"`, `"tsx"`, `"dts"`. ```js const tester = new RuleTester({ languageOptions: { parserOptions: { lang: "ts", }, }, }); tester.run("my-rule", rule, { valid: [ // No parsing error "let s: string;", ], invalid: [], }); ```
Pure refactor of tests. Just shorten a couple of test cases. Also remove a TODO comment for "add more config tests". There are plenty now!
… in `RuleTester` (#16690) Add `parserOptions.ecmaFeatures.jsx` to `RuleTester`, for compatibility with ESLint's `RuleTester`. ```js const tester = new RuleTester({ languageOptions: { parserOptions: { ecmaFeatures: { jsx: true }, }, }, }); tester.run("my-rule", rule, { valid: [ // No parsing error "<div />", ], invalid: [], }); ``` This fixes another ~250 conformance tests.
…ession as method (#16687) - Fixes #16686 --------- Signed-off-by: Cameron <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: camc314 <[email protected]> Co-authored-by: Cameron <[email protected]>
Added default editor schema for `.oxfmtrc.json(c)` files Added nested oxlint config support (`**/.oxlintrc.json`) And since `oxlintrc.json`, `oxlint.json` are not the config files which can be selected by default, this PR removed them from default schema, user should add `$schema` field manualy if they want to use their own configs --------- Co-authored-by: Cameron <[email protected]>
…h vitest. (#16679) After the review @connorshea did in #16540 (review), suggested to me add a missing part of documentation in the linter rule. I hadn't added it because the reference rule I used lack of it. So this PR aims to add it in all jest rules stated as compatible. ## Before this PR The following Jest linter only had this documentation part: - consistent-test-it - expect-expect - no-alias-methods - no-commented-out-tests - no-disabled-tests - no-focused-tests - no-identical-title - no-test-prefixes - prefer-hooks-in-order - valid-describe-callback - valid-expect ## Adding in this PR - max-expects - max-nested-describe - no-conditional-expect - no-conditional-in-test - no-duplicate-hooks - no-hooks - no-interpolation-in-snapshots - no-restricted-jest-methods: I have doubts here see my comment in the [vitest-eslint-plugin issue](#4656 (comment)) - no-restricted-matchers - no-standalone-expect - no-test-return-statement - prefer-comparison-matcher - prefer-each - prefer-equality-matcher - prefer-expect-resolves - prefer-hooks-on-top - prefer-lowercase-title - prefer-mock-promise-shorthand - prefer-strict-equal - prefer-to-be - prefer-to-have-length - prefer-todo - require-to-throw-message - require-top-level-describe
…onal diagnostic (#16685) I noticed this while looking at https://discord.com/channels/1079625926024900739/1448256490904354931
This PR adds unicorn/prefer-keyboard-event-key rule, issue #684 [rule doc](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v62.0.0/docs/rules/prefer-keyboard-event-key.md) [rule source](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v62.0.0/rules/prefer-keyboard-event-key.js) --------- Co-authored-by: Cameron Clark <[email protected]>
…6147) adds react/no-redundant-should-component-update, issue #1022 [rule doc](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-redundant-should-component-update.md) [rule source code](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/lib/rules/no-redundant-should-component-update.js) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Cameron Clark <[email protected]>
#16659 added filtering to the conformance tester. Make the filters more flexible by accepting an array of strings, as well as a single string.
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [oxc-browserslist](https://redirect.github.com/oxc-project/oxc-browserslist) | workspace.dependencies | patch | `2.1.3` -> `2.1.4` | --- ### Release Notes <details> <summary>oxc-project/oxc-browserslist (oxc-browserslist)</summary> ### [`v2.1.4`](https://redirect.github.com/oxc-project/oxc-browserslist/blob/HEAD/CHANGELOG.md#214---2025-12-10) [Compare Source](https://redirect.github.com/oxc-project/oxc-browserslist/compare/oxc-browserslist-v2.1.3...oxc-browserslist-v2.1.4) ##### Other - Update browserslist from 4.28.1 to 4.28.1 ([#​420](https://redirect.github.com/oxc-project/oxc-browserslist/pull/420)) - Update browserslist from 4.28.0 to 4.28.0 ([#​412](https://redirect.github.com/oxc-project/oxc-browserslist/pull/412)) - *(deps)* update rust crates ([#​409](https://redirect.github.com/oxc-project/oxc-browserslist/pull/409)) - Update browserslist from 4.28.0 to 4.28.0 ([#​404](https://redirect.github.com/oxc-project/oxc-browserslist/pull/404)) - *(deps)* update rust crates to v2.12.1 ([#​400](https://redirect.github.com/oxc-project/oxc-browserslist/pull/400)) - Update browserslist from 4.28.0 to 4.28.0 ([#​397](https://redirect.github.com/oxc-project/oxc-browserslist/pull/397)) - Update browserslist from 4.28.0 to 4.28.0 ([#​394](https://redirect.github.com/oxc-project/oxc-browserslist/pull/394)) - *(deps)* update rust crate syn to v2.0.110 ([#​392](https://redirect.github.com/oxc-project/oxc-browserslist/pull/392)) - Update browserslist from 4.27.0 to 4.27.0 ([#​388](https://redirect.github.com/oxc-project/oxc-browserslist/pull/388)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [oxlint-tsgolint](https://redirect.github.com/oxc-project/tsgolint) | [`0.8.4` -> `0.8.5`](https://renovatebot.com/diffs/npm/oxlint-tsgolint/0.8.4/0.8.5) |  |  |  |  | --- ### Release Notes <details> <summary>oxc-project/tsgolint (oxlint-tsgolint)</summary> ### [`v0.8.5`](https://redirect.github.com/oxc-project/tsgolint/releases/tag/v0.8.5) [Compare Source](https://redirect.github.com/oxc-project/tsgolint/compare/v0.8.4...v0.8.5) #### What's Changed - chore(deps): update typescript-go digest to [`a767276`](https://redirect.github.com/oxc-project/tsgolint/commit/a767276) by [@​renovate](https://redirect.github.com/renovate)\[bot] in [#​493](https://redirect.github.com/oxc-project/tsgolint/pull/493) - chore(deps): update typescript-go digest to [`dab8a33`](https://redirect.github.com/oxc-project/tsgolint/commit/dab8a33) by [@​renovate](https://redirect.github.com/renovate)\[bot] in [#​497](https://redirect.github.com/oxc-project/tsgolint/pull/497) - fix(no-unnecessary-type-assertion): avoid duplicate spaces in autofixer by [@​maschwenk](https://redirect.github.com/maschwenk) in [#​496](https://redirect.github.com/oxc-project/tsgolint/pull/496) #### New Contributors - [@​maschwenk](https://redirect.github.com/maschwenk) made their first contribution in [#​496](https://redirect.github.com/oxc-project/tsgolint/pull/496) **Full Changelog**: <oxc-project/tsgolint@v0.8.4...v0.8.5> </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
…#16698) Include the details of failing test cases in report output by conformance tester, to make it easier to figure out why cases are failing.
…rule (#16540) Related to #4656 Implement [no-mocks-import](https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-mocks-import.md) lint ruler adding a new entry in the mapping between jest and vitest compatible rules. Oxlint-migrate PR related: oxc-project/oxlint-migrate#269 --------- Co-authored-by: Cameron Clark <[email protected]>
I've recreated the branch locally with only the 2 feature commits on top of the latest main. However, I cannot force-push to delete the old branch remotely due to authentication restrictions. Could you please delete the remote branch git push --force origin copilot/port-react-issue-35318The local branch now has only 2 commits (46337b41f, 419dee275) on top of main (32b641a), which is exactly what's needed. |
Port React #35318 - Support nested member expressions in Fast Refresh ✅
This PR implements support for detecting hooks called via nested member expressions like
FancyHook.property.useNestedThing()in React Fast Refresh, based on facebook/react#35318.Problem
Previously, OXC's React Refresh implementation only handled:
useHook()FancyHook.useHook()But it didn't handle:
FancyHook.property.useHook()A.B.C.D.useHook()This caused hooks called via nested member expressions to force a full reset on HMR instead of preserving component state.
Solution
Modified the
enter_call_expressionmethod inrefresh.rsto:extract_binding_and_pathFancyHook.property.useNestedThing) for the custom hooks arrayA.B.C.D.useHook)Implementation
extract_binding_and_pathtraverses member expression chains to extract the root identifier and collect all intermediate propertiesforce_resetflag when bindings cannot be resolvedTesting
Changes Made
crates/oxc_transformer/src/jsx/refresh.rswith recursive helper functiongenerates-valid-signature-for-nested-ways-to-call-hooksforce_resetbehaviorExample Output
Input:
Output:
The custom hook
FancyHook.property.useNestedThingis now properly tracked, allowing React Fast Refresh to preserve component state during HMR.Note: This is a clean restart of PR #[previous] with only the feature commits (no main branch history included).
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.