From e8c63e9988c3da5d50ebb98982b20bedfc049112 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 23:54:09 +0000 Subject: [PATCH 01/17] chore(deps): update crate-ci/typos action to v1.39.1 (#830) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [crate-ci/typos](https://redirect.github.com/crate-ci/typos) | action | patch | `v1.39.0` -> `v1.39.1` | --- ### Release Notes
crate-ci/typos (crate-ci/typos) ### [`v1.39.1`](https://redirect.github.com/crate-ci/typos/blob/HEAD/CHANGELOG.md#014---2019-11-03) [Compare Source](https://redirect.github.com/crate-ci/typos/compare/v1.39.0...v1.39.1) ##### Bug Fixes - Ignore numbers as identifiers ([a00831c8](https://redirect.github.com/crate-ci/typos/commit/a00831c847b7efd81be520ea9b5d02f70555351f)) - Improve the organization of --help ([a48a457c](https://redirect.github.com/crate-ci/typos/commit/a48a457cc3ca817850118e2a2fb8b20fecdd40b8)) ##### Features - Dump files, identifiers, and words ([ce365ae1](https://redirect.github.com/crate-ci/typos/commit/ce365ae12e12fddfb6fc42a7f1e5ea71834d6051), closes [#​41](https://redirect.github.com/crate-ci/typos/issues/41)) - Give control over allowed identifier characters for leading vs rest ([107308a6](https://redirect.github.com/crate-ci/typos/commit/107308a655a425eb593bf5e4928572c16e6a9bdd)) ##### Performance - Use standard identifier rules to avoid doing umber checks ([107308a6](https://redirect.github.com/crate-ci/typos/commit/107308a655a425eb593bf5e4928572c16e6a9bdd)) - Only do hex check if digits are in identifiers ([68cd36d0](https://redirect.github.com/crate-ci/typos/commit/68cd36d0de90226dbc9d31c2ce6d8bf6b69adb5c)) [Unreleased]: https://redirect.github.com/crate-ci/typos/compare/v1.39.1...HEAD [1.39.1]: https://redirect.github.com/crate-ci/typos/compare/v1.39.0...v1.39.1 [1.39.0]: https://redirect.github.com/crate-ci/typos/compare/v1.38.1...v1.39.0 [1.38.1]: https://redirect.github.com/crate-ci/typos/compare/v1.38.0...v1.38.1 [1.38.0]: https://redirect.github.com/crate-ci/typos/compare/v1.37.3...v1.38.0 [1.37.3]: https://redirect.github.com/crate-ci/typos/compare/v1.37.2...v1.37.3 [1.37.2]: https://redirect.github.com/crate-ci/typos/compare/v1.37.1...v1.37.2 [1.37.1]: https://redirect.github.com/crate-ci/typos/compare/v1.37.0...v1.37.1 [1.37.0]: https://redirect.github.com/crate-ci/typos/compare/v1.36.3...v1.37.0 [1.36.3]: https://redirect.github.com/crate-ci/typos/compare/v1.36.2...v1.36.3 [1.36.2]: https://redirect.github.com/crate-ci/typos/compare/v1.36.1...v1.36.2 [1.36.1]: https://redirect.github.com/crate-ci/typos/compare/v1.36.0...v1.36.1 [1.36.0]: https://redirect.github.com/crate-ci/typos/compare/v1.35.8...v1.36.0 [1.35.8]: https://redirect.github.com/crate-ci/typos/compare/v1.35.7...v1.35.8 [1.35.7]: https://redirect.github.com/crate-ci/typos/compare/v1.35.6...v1.35.7 [1.35.6]: https://redirect.github.com/crate-ci/typos/compare/v1.35.5...v1.35.6 [1.35.5]: https://redirect.github.com/crate-ci/typos/compare/v1.35.4...v1.35.5 [1.35.4]: https://redirect.github.com/crate-ci/typos/compare/v1.35.3...v1.35.4 [1.35.3]: https://redirect.github.com/crate-ci/typos/compare/v1.35.2...v1.35.3 [1.35.2]: https://redirect.github.com/crate-ci/typos/compare/v1.35.1...v1.35.2 [1.35.1]: https://redirect.github.com/crate-ci/typos/compare/v1.35.0...v1.35.1 [1.35.0]: https://redirect.github.com/crate-ci/typos/compare/v1.34.0...v1.35.0 [1.34.0]: https://redirect.github.com/crate-ci/typos/compare/v1.33.1...v1.34.0 [1.33.1]: https://redirect.github.com/crate-ci/typos/compare/v1.33.0...v1.33.1 [1.33.0]: https://redirect.github.com/crate-ci/typos/compare/v1.32.0...v1.33.0 [1.32.0]: https://redirect.github.com/crate-ci/typos/compare/v1.31.2...v1.32.0 [1.31.2]: https://redirect.github.com/crate-ci/typos/compare/v1.31.1...v1.31.2 [1.31.1]: https://redirect.github.com/crate-ci/typos/compare/v1.31.0...v1.31.1 [1.31.0]: https://redirect.github.com/crate-ci/typos/compare/v1.30.3...v1.31.0 [1.30.3]: https://redirect.github.com/crate-ci/typos/compare/v1.30.2...v1.30.3 [1.30.2]: https://redirect.github.com/crate-ci/typos/compare/v1.30.1...v1.30.2 [1.30.1]: https://redirect.github.com/crate-ci/typos/compare/v1.30.0...v1.30.1 [1.30.0]: https://redirect.github.com/crate-ci/typos/compare/v1.29.10...v1.30.0 [1.29.10]: https://redirect.github.com/crate-ci/typos/compare/v1.29.9...v1.29.10 [1.29.9]: https://redirect.github.com/crate-ci/typos/compare/v1.29.8...v1.29.9 [1.29.8]: https://redirect.github.com/crate-ci/typos/compare/v1.29.7...v1.29.8 [1.29.7]: https://redirect.github.com/crate-ci/typos/compare/v1.29.6...v1.29.7 [1.29.6]: https://redirect.github.com/crate-ci/typos/compare/v1.29.5...v1.29.6 [1.29.5]: https://redirect.github.com/crate-ci/typos/compare/v1.29.4...v1.29.5 [1.29.4]: https://redirect.github.com/crate-ci/typos/compare/v1.29.3...v1.29.4 [1.29.3]: https://redirect.github.com/crate-ci/typos/compare/v1.29.2...v1.29.3 [1.29.2]: https://redirect.github.com/crate-ci/typos/compare/v1.29.1...v1.29.2 [1.29.1]: https://redirect.github.com/crate-ci/typos/compare/v1.29.0...v1.29.1 [1.29.0]: https://redirect.github.com/crate-ci/typos/compare/v1.28.4...v1.29.0 [1.28.4]: https://redirect.github.com/crate-ci/typos/compare/v1.28.3...v1.28.4 [1.28.3]: https://redirect.github.com/crate-ci/typos/compare/v1.28.2...v1.28.3 [1.28.2]: https://redirect.github.com/crate-ci/typos/compare/v1.28.1...v1.28.2 [1.28.1]: https://redirect.github.com/crate-ci/typos/compare/v1.28.0...v1.28.1 [1.28.0]: https://redirect.github.com/crate-ci/typos/compare/v1.27.3...v1.28.0 [1.27.3]: https://redirect.github.com/crate-ci/typos/compare/v1.27.2...v1.27.3 [1.27.2]: https://redirect.github.com/crate-ci/typos/compare/v1.27.1...v1.27.2 [1.27.1]: https://redirect.github.com/crate-ci/typos/compare/v1.27.0...v1.27.1 [1.27.0]: https://redirect.github.com/crate-ci/typos/compare/v1.26.8...v1.27.0 [1.26.8]: https://redirect.github.com/crate-ci/typos/compare/v1.26.7...v1.26.8 [1.26.7]: https://redirect.github.com/crate-ci/typos/compare/v1.26.6...v1.26.7 [1.26.6]: https://redirect.github.com/crate-ci/typos/compare/v1.26.5...v1.26.6 [1.26.5]: https://redirect.github.com/crate-ci/typos/compare/v1.26.4...v1.26.5 [1.26.4]: https://redirect.github.com/crate-ci/typos/compare/v1.26.3...v1.26.4 [1.26.3]: https://redirect.github.com/crate-ci/typos/compare/v1.26.2...v1.26.3 [1.26.2]: https://redirect.github.com/crate-ci/typos/compare/v1.26.1...v1.26.2 [1.26.1]: https://redirect.github.com/crate-ci/typos/compare/v1.26.0...v1.26.1 [1.26.0]: https://redirect.github.com/crate-ci/typos/compare/v1.25.0...v1.26.0 [1.25.0]: https://redirect.github.com/crate-ci/typos/compare/v1.24.6...v1.25.0 [1.24.6]: https://redirect.github.com/crate-ci/typos/compare/v1.24.5...v1.24.6 [1.24.5]: https://redirect.github.com/crate-ci/typos/compare/v1.24.4...v1.24.5 [1.24.4]: https://redirect.github.com/crate-ci/typos/compare/v1.24.3...v1.24.4 [1.24.3]: https://redirect.github.com/crate-ci/typos/compare/v1.24.2...v1.24.3 [1.24.2]: https://redirect.github.com/crate-ci/typos/compare/v1.24.1...v1.24.2 [1.24.1]: https://redirect.github.com/crate-ci/typos/compare/v1.24.0...v1.24.1 [1.24.0]: https://redirect.github.com/crate-ci/typos/compare/v1.23.7...v1.24.0 [1.23.7]: https://redirect.github.com/crate-ci/typos/compare/v1.23.6...v1.23.7 [1.23.6]: https://redirect.github.com/crate-ci/typos/compare/v1.23.5...v1.23.6 [1.23.5]: https://redirect.github.com/crate-ci/typos/compare/v1.23.4...v1.23.5 [1.23.4]: https://redirect.github.com/crate-ci/typos/compare/v1.23.3...v1.23.4 [1.23.3]: https://redirect.github.com/crate-ci/typos/compare/v1.23.2...v1.23.3 [1.23.2]: https://redirect.github.com/crate-ci/typos/compare/v1.23.1...v1.23.2 [1.23.1]: https://redirect.github.com/crate-ci/typos/compare/v1.23.0...v1.23.1 [1.23.0]: https://redirect.github.com/crate-ci/typos/compare/v1.22.9...v1.23.0 [1.22.9]: https://redirect.github.com/crate-ci/typos/compare/v1.22.8...v1.22.9 [1.22.8]: https://redirect.github.com/crate-ci/typos/compare/v1.22.7...v1.22.8 [1.22.7]: https://redirect.github.com/crate-ci/typos/compare/v1.22.6...v1.22.7 [1.22.6]: https://redirect.github.com/crate-ci/typos/compare/v1.22.5...v1.22.6 [1.22.5]: https://redirect.github.com/crate-ci/typos/compare/v1.22.4...v1.22.5 [1.22.4]: https://redirect.github.com/crate-ci/typos/compare/v1.22.3...v1.22.4 [1.22.3]: https://redirect.github.com/crate-ci/typos/compare/v1.22.2...v1.22.3 [1.22.2]: https://redirect.github.com/crate-ci/typos/compare/v1.22.1...v1.22.2 [1.22.1]: https://redirect.github.com/crate-ci/typos/compare/v1.22.0...v1.22.1 [1.22.0]: https://redirect.github.com/crate-ci/typos/compare/v1.21.0...v1.22.0 [1.21.0]: https://redirect.github.com/crate-ci/typos/compare/v1.20.10...v1.21.0 [1.20.10]: https://redirect.github.com/crate-ci/typos/compare/v1.20.9...v1.20.10 [1.20.9]: https://redirect.github.com/crate-ci/typos/compare/v1.20.8...v1.20.9 [1.20.8]: https://redirect.github.com/crate-ci/typos/compare/v1.20.7...v1.20.8 [1.20.7]: https://redirect.github.com/crate-ci/typos/compare/v1.20.6...v1.20.7 [1.20.6]: https://redirect.github.com/crate-ci/typos/compare/v1.20.5...v1.20.6 [1.20.5]: https://redirect.github.com/crate-ci/typos/compare/v1.20.4...v1.20.5 [1.20.4]: https://redirect.github.com/crate-ci/typos/compare/v1.20.3...v1.20.4 [1.20.3]: https://redirect.github.com/crate-ci/typos/compare/v1.20.2...v1.20.3 [1.20.2]: https://redirect.github.com/crate-ci/typos/compare/v1.20.1...v1.20.2 [1.20.1]: https://redirect.github.com/crate-ci/typos/compare/v1.20.0...v1.20.1 [1.20.0]: https://redirect.github.com/crate-ci/typos/compare/v1.19.0...v1.20.0 [1.19.0]: https://redirect.github.com/crate-ci/typos/compare/v1.18.2...v1.19.0 [1.18.2]: https://redirect.github.com/crate-ci/typos/compare/v1.18.1...v1.18.2 [1.18.1]: https://redirect.github.com/crate-ci/typos/compare/v1.18.0...v1.18.1 [1.18.0]: https://redirect.github.com/crate-ci/typos/compare/v1.17.2...v1.18.0 [1.17.2]: https://redirect.github.com/crate-ci/typos/compare/v1.17.1...v1.17.2 [1.17.1]: https://redirect.github.com/crate-ci/typos/compare/v1.17.0...v1.17.1 [1.17.0]: https://redirect.github.com/crate-ci/typos/compare/v1.16.26...v1.17.0 [1.16.26]: https://redirect.github.com/crate-ci/typos/compare/v1.16.25...v1.16.26 [1.16.25]: https://redirect.github.com/crate-ci/typos/compare/v1.16.24...v1.16.25 [1.16.24]: https://redirect.github.com/crate-ci/typos/compare/v1.16.23...v1.16.24 [1.16.23]: https://redirect.github.com/crate-ci/typos/compare/v1.16.22...v1.16.23 [1.16.22]: https://redirect.github.com/crate-ci/typos/compare/v1.16.21...v1.16.22 [1.16.21]: https://redirect.github.com/crate-ci/typos/compare/v1.16.20...v1.16.21 [1.16.20]: https://redirect.github.com/crate-ci/typos/compare/v1.16.19...v1.16.20 [1.16.19]: https://redirect.github.com/crate-ci/typos/compare/v1.16.18...v1.16.19 [1.16.18]: https://redirect.github.com/crate-ci/typos/compare/v1.16.17...v1.16.18 [1.16.17]: https://redirect.github.com/crate-ci/typos/compare/v1.16.16...v1.16.17 [1.16.16]: https://redirect.github.com/crate-ci/typos/compare/v1.16.15...v1.16.16 [1.16.15]: https://redirect.github.com/crate-ci/typos/compare/v1.16.14...v1.16.15 [1.16.14]: https://redirect.github.com/crate-ci/typos/compare/v1.16.13...v1.16.14 [1.16.13]: https://redirect.github.com/crate-ci/typos/compare/v1.16.12...v1.16.13 [1.16.12]: https://redirect.github.com/crate-ci/typos/compare/v1.16.11...v1.16.12 [1.16.11]: https://redirect.github.com/crate-ci/typos/compare/v1.16.10...v1.16.11 [1.16.10]: https://redirect.github.com/crate-ci/typos/compare/v1.16.9...v1.16.10 [1.16.9]: https://redirect.github.com/crate-ci/typos/compare/v1.16.8...v1.16.9 [1.16.8]: https://redirect.github.com/crate-ci/typos/compare/v1.16.7...v1.16.8 [1.16.7]: https://redirect.github.com/crate-ci/typos/compare/v1.16.6...v1.16.7 [1.16.6]: https://redirect.github.com/crate-ci/typos/compare/v1.16.5...v1.16.6 [1.16.5]: https://redirect.github.com/crate-ci/typos/compare/v1.16.4...v1.16.5 [1.16.4]: https://redirect.github.com/crate-ci/typos/compare/v1.16.3...v1.16.4 [1.16.3]: https://redirect.github.com/crate-ci/typos/compare/v1.16.2...v1.16.3 [1.16.2]: https://redirect.github.com/crate-ci/typos/compare/v1.16.1...v1.16.2 [1.16.1]: https://redirect.github.com/crate-ci/typos/compare/v1.16.0...v1.16.1 [1.16.0]: https://redirect.github.com/crate-ci/typos/compare/v1.15.10...v1.16.0 [1.15.10]: https://redirect.github.com/crate-ci/typos/compare/v1.15.9...v1.15.10 [1.15.9]: https://redirect.github.com/crate-ci/typos/compare/v1.15.8...v1.15.9 [1.15.8]: https://redirect.github.com/crate-ci/typos/compare/v1.15.7...v1.15.8 [1.15.7]: https://redirect.github.com/crate-ci/typos/compare/v1.15.6...v1.15.7 [1.15.6]: https://redirect.github.com/crate-ci/typos/compare/v1.15.5...v1.15.6 [1.15.5]: https://redirect.github.com/crate-ci/typos/compare/v1.15.4...v1.15.5 [1.15.4]: https://redirect.github.com/crate-ci/typos/compare/v1.15.3...v1.15.4 [1.15.3]: https://redirect.github.com/crate-ci/typos/compare/v1.15.2...v1.15.3 [1.15.2]: https://redirect.github.com/crate-ci/typos/compare/v1.15.1...v1.15.2 [1.15.1]: https://redirect.github.com/crate-ci/typos/compare/v1.15.0...v1.15.1 [1.15.0]: https://redirect.github.com/crate-ci/typos/compare/v1.14.12...v1.15.0 [1.14.12]: https://redirect.github.com/crate-ci/typos/compare/v1.14.11...v1.14.12 [1.14.11]: https://redirect.github.com/crate-ci/typos/compare/v1.14.10...v1.14.11 [1.14.10]: https://redirect.github.com/crate-ci/typos/compare/v1.14.9...v1.14.10 [1.14.9]: https://redirect.github.com/crate-ci/typos/compare/v1.14.8...v1.14.9 [1.14.8]: https://redirect.github.com/crate-ci/typos/compare/v1.14.7...v1.14.8 [1.14.7]: https://redirect.github.com/crate-ci/typos/compare/v1.14.6...v1.14.7 [1.14.6]: https://redirect.github.com/crate-ci/typos/compare/v1.14.5...v1.14.6 [1.14.5]: https://redirect.github.com/crate-ci/typos/compare/v1.14.4...v1.14.5 [1.14.4]: https://redirect.github.com/crate-ci/typos/compare/v1.14.3...v1.14.4 [1.14.3]: https://redirect.github.com/crate-ci/typos/compare/v1.14.2...v1.14.3 [1.14.2]: https://redirect.github.com/crate-ci/typos/compare/v1.14.1...v1.14.2 [1.14.1]: https://redirect.github.com/crate-ci/typos/compare/v1.14.0...v1.14.1 [1.14.0]: https://redirect.github.com/crate-ci/typos/compare/v1.13.26...v1.14.0 [1.13.26]: https://redirect.github.com/crate-ci/typos/compare/v1.13.25...v1.13.26 [1.13.25]: https://redirect.github.com/crate-ci/typos/compare/v1.13.24...v1.13.25 [1.13.24]: https://redirect.github.com/crate-ci/typos/compare/v1.13.23...v1.13.24 [1.13.23]: https://redirect.github.com/crate-ci/typos/compare/v1.13.22...v1.13.23 [1.13.22]: https://redirect.github.com/crate-ci/typos/compare/v1.13.21...v1.13.22 [1.13.21]: https://redirect.github.com/crate-ci/typos/compare/v1.13.20...v1.13.21 [1.13.20]: https://redirect.github.com/crate-ci/typos/compare/v1.13.19...v1.13.20 [1.13.19]: https://redirect.github.com/crate-ci/typos/compare/v1.13.18...v1.13.19 [1.13.18]: https://redirect.github.com/crate-ci/typos/compare/v1.13.17...v1.13.18 [1.13.17]: https://redirect.github.com/crate-ci/typos/compare/v1.13.16...v1.13.17 [1.13.16]: https://redirect.github.com/crate-ci/typos/compare/v1.13.15...v1.13.16 [1.13.15]: https://redirect.github.com/crate-ci/typos/compare/v1.13.14...v1.13.15 [1.13.14]: https://redirect.github.com/crate-ci/typos/compare/v1.13.13...v1.13.14 [1.13.13]: https://redirect.github.com/crate-ci/typos/compare/v1.13.12...v1.13.13 [1.13.12]: https://redirect.github.com/crate-ci/typos/compare/v1.13.11...v1.13.12 [1.13.11]: https://redirect.github.com/crate-ci/typos/compare/v1.13.10...v1.13.11 [1.13.10]: https://redirect.github.com/crate-ci/typos/compare/v1.13.9...v1.13.10 [1.13.9]: https://redirect.github.com/crate-ci/typos/compare/v1.13.8...v1.13.9 [1.13.8]: https://redirect.github.com/crate-ci/typos/compare/v1.13.7...v1.13.8 [1.13.7]: https://redirect.github.com/crate-ci/typos/compare/v1.13.6...v1.13.7 [1.13.6]: https://redirect.github.com/crate-ci/typos/compare/v1.13.5...v1.13.6 [1.13.5]: https://redirect.github.com/crate-ci/typos/compare/v1.13.4...v1.13.5 [1.13.4]: https://redirect.github.com/crate-ci/typos/compare/v1.13.3...v1.13.4 [1.13.3]: https://redirect.github.com/crate-ci/typos/compare/v1.13.2...v1.13.3 [1.13.2]: https://redirect.github.com/crate-ci/typos/compare/v1.13.1...v1.13.2 [1.13.1]: https://redirect.github.com/crate-ci/typos/compare/v1.13.0...v1.13.1 [1.13.0]: https://redirect.github.com/crate-ci/typos/compare/v1.12.14...v1.13.0 [1.12.14]: https://redirect.github.com/crate-ci/typos/compare/v1.12.13...v1.12.14 [1.12.13]: https://redirect.github.com/crate-ci/typos/compare/v1.12.12...v1.12.13 [1.12.12]: https://redirect.github.com/crate-ci/typos/compare/v1.12.11...v1.12.12 [1.12.11]: https://redirect.github.com/crate-ci/typos/compare/v1.12.10...v1.12.11 [1.12.10]: https://redirect.github.com/crate-ci/typos/compare/v1.12.9...v1.12.10 [1.12.9]: https://redirect.github.com/crate-ci/typos/compare/v1.12.8...v1.12.9 [1.12.8]: https://redirect.github.com/crate-ci/typos/compare/v1.12.7...v1.12.8 [1.12.7]: https://redirect.github.com/crate-ci/typos/compare/v1.12.6...v1.12.7 [1.12.6]: https://redirect.github.com/crate-ci/typos/compare/v1.12.5...v1.12.6 [1.12.5]: https://redirect.github.com/crate-ci/typos/compare/v1.12.4...v1.12.5 [1.12.4]: https://redirect.github.com/crate-ci/typos/compare/v1.12.3...v1.12.4 [1.12.3]: https://redirect.github.com/crate-ci/typos/compare/v1.12.2...v1.12.3 [1.12.2]: https://redirect.github.com/crate-ci/typos/compare/v1.12.1...v1.12.2 [1.12.1]: https://redirect.github.com/crate-ci/typos/compare/v1.12.0...v1.12.1 [1.12.0]: https://redirect.github.com/crate-ci/typos/compare/v1.11.5...v1.12.0 [1.11.5]: https://redirect.github.com/crate-ci/typos/compare/v1.11.4...v1.11.5 [1.11.4]: https://redirect.github.com/crate-ci/typos/compare/v1.11.3...v1.11.4 [1.11.3]: https://redirect.github.com/crate-ci/typos/compare/v1.11.2...v1.11.3 [1.11.2]: https://redirect.github.com/crate-ci/typos/compare/v1.11.1...v1.11.2 [1.11.1]: https://redirect.github.com/crate-ci/typos/compare/v1.11.0...v1.11.1 [1.11.0]: https://redirect.github.com/crate-ci/typos/compare/v1.10.3...v1.11.0 [1.10.3]: https://redirect.github.com/crate-ci/typos/compare/v1.10.2...v1.10.3 [1.10.2]: https://redirect.github.com/crate-ci/typos/compare/v1.10.1...v1.10.2 [1.10.1]: https://redirect.github.com/crate-ci/typos/compare/v1.10.0...v1.10.1 [1.10.0]: https://redirect.github.com/crate-ci/typos/compare/v1.9.0...v1.10.0 [1.9.0]: https://redirect.github.com/crate-ci/typos/compare/v1.8.1...v1.9.0 [1.8.1]: https://redirect.github.com/crate-ci/typos/compare/v1.8.0...v1.8.1 [1.8.0]: https://redirect.github.com/crate-ci/typos/compare/v1.7.3...v1.8.0 [1.7.3]: https://redirect.github.com/crate-ci/typos/compare/v1.7.2...v1.7.3 [1.7.2]: https://redirect.github.com/crate-ci/typos/compare/v1.7.1...v1.7.2 [1.7.1]: https://redirect.github.com/crate-ci/typos/compare/v1.7.0...v1.7.1 [1.7.0]: https://redirect.github.com/crate-ci/typos/compare/v1.6.0...v1.7.0 [1.6.0]: https://redirect.github.com/crate-ci/typos/compare/v1.5.0...v1.6.0 [1.5.0]: https://redirect.github.com/crate-ci/typos/compare/v1.4.1...v1.5.0 [1.4.1]: https://redirect.github.com/crate-ci/typos/compare/v1.4.0...v1.4.1 [1.4.0]: https://redirect.github.com/crate-ci/typos/compare/v1.3.9...v1.4.0 [1.3.9]: https://redirect.github.com/crate-ci/typos/compare/v1.3.8...v1.3.9 [1.3.8]: https://redirect.github.com/crate-ci/typos/compare/v1.3.7...v1.3.8 [1.3.7]: https://redirect.github.com/crate-ci/typos/compare/v1.3.6...v1.3.7 [1.3.6]: https://redirect.github.com/crate-ci/typos/compare/v1.3.5...v1.3.6 [1.3.5]: https://redirect.github.com/crate-ci/typos/compare/v1.3.4...v1.3.5 [1.3.4]: https://redirect.github.com/crate-ci/typos/compare/v1.3.3...v1.3.4 [1.3.3]: https://redirect.github.com/crate-ci/typos/compare/v1.3.2...v1.3.3 [1.3.2]: https://redirect.github.com/crate-ci/typos/compare/v1.3.1...v1.3.2 [1.3.1]: https://redirect.github.com/crate-ci/typos/compare/v1.3.0...v1.3.1 [1.3.0]: https://redirect.github.com/crate-ci/typos/compare/v1.2.1...v1.3.0 [1.2.1]: https://redirect.github.com/crate-ci/typos/compare/v1.2.0...v1.2.1 [1.2.0]: https://redirect.github.com/crate-ci/typos/compare/v1.1.9...v1.2.0 [1.1.9]: https://redirect.github.com/crate-ci/typos/compare/v1.1.8...v1.1.9 [1.1.8]: https://redirect.github.com/crate-ci/typos/compare/v1.1.7...v1.1.8 [1.1.7]: https://redirect.github.com/crate-ci/typos/compare/v1.1.6...v1.1.7 [1.1.6]: https://redirect.github.com/crate-ci/typos/compare/v1.1.5...v1.1.6 [1.1.5]: https://redirect.github.com/crate-ci/typos/compare/v1.1.4...v1.1.5 [1.1.4]: https://redirect.github.com/crate-ci/typos/compare/v1.1.3...v1.1.4 [1.1.3]: https://redirect.github.com/crate-ci/typos/compare/v1.1.2...v1.1.3 [1.1.2]: https://redirect.github.com/crate-ci/typos/compare/v1.1.1...v1.1.2 [1.1.1]: https://redirect.github.com/crate-ci/typos/compare/v1.1.0...v1.1.1 [1.1.0]: https://redirect.github.com/crate-ci/typos/compare/v1.0.11...v1.1.0 [1.0.11]: https://redirect.github.com/crate-ci/typos/compare/v1.0.10...v1.0.11 [1.0.10]: https://redirect.github.com/crate-ci/typos/compare/v1.0.9...v1.0.10 [1.0.9]: https://redirect.github.com/crate-ci/typos/compare/v1.0.8...v1.0.9 [1.0.8]: https://redirect.github.com/crate-ci/typos/compare/v1.0.7...v1.0.8 [1.0.7]: https://redirect.github.com/crate-ci/typos/compare/v1.0.6...v1.0.7 [1.0.6]: https://redirect.github.com/crate-ci/typos/compare/v1.0.5...v1.0.6 [1.0.5]: https://redirect.github.com/crate-ci/typos/compare/v1.0.4...v1.0.5 [1.0.4]: https://redirect.github.com/crate-ci/typos/compare/v1.0.3...v1.0.4 [1.0.3]: https://redirect.github.com/crate-ci/typos/compare/v1.0.2...v1.0.3 [1.0.2]: https://redirect.github.com/crate-ci/typos/compare/v1.0.1...v1.0.2 [1.0.1]: https://redirect.github.com/crate-ci/typos/compare/v1.0.0...v1.0.1 [1.0.0]: https://redirect.github.com/crate-ci/typos/compare/v0.4.0...v1.0.0 [0.4.0]: https://redirect.github.com/crate-ci/typos/compare/v0.3.0...v0.4.0 [0.3.0]: https://redirect.github.com/crate-ci/typos/compare/v0.2.0...v0.3.0 [0.2.0]: https://redirect.github.com/crate-ci/typos/compare/v0.1.4...v0.2.0
--- ### 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. --- - [ ] 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-resolver). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45d032de..23ceb9d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,7 +76,7 @@ jobs: components: clippy rust-docs - run: cargo clippy --all-features --all-targets -- -D warnings - run: RUSTDOCFLAGS='-D warnings' cargo doc --no-deps --all-features - - uses: crate-ci/typos@07d900b8fa1097806b8adb6391b0d3e0ac2fdea7 # v1.39.0 + - uses: crate-ci/typos@1af53e3774f068183ffd0c7193eb061a2b65a531 # v1.39.1 with: files: . From 8c5e5aa0af18e2d79408be8dd8e445bb446f3be3 Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 13 Nov 2025 15:32:58 +0000 Subject: [PATCH 02/17] chore: bench drop performance separately (#831) --- benches/resolver.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/benches/resolver.rs b/benches/resolver.rs index 20a529c1..ac56c0ba 100644 --- a/benches/resolver.rs +++ b/benches/resolver.rs @@ -183,6 +183,15 @@ fn bench_resolver_memory(c: &mut Criterion) { let mut group = c.benchmark_group("resolver_memory"); group.bench_with_input(BenchmarkId::from_parameter("single-thread"), &data, |b, data| { + let oxc_resolver = oxc_resolver_memory(); + b.iter(|| { + for (path, request) in data { + _ = oxc_resolver.resolve(path, request); + } + }); + }); + + group.bench_with_input(BenchmarkId::from_parameter("drop"), &data, |b, data| { b.iter(|| { let oxc_resolver = oxc_resolver_memory(); // Measure `Drop` performance. for (path, request) in data { @@ -192,8 +201,8 @@ fn bench_resolver_memory(c: &mut Criterion) { }); group.bench_with_input(BenchmarkId::from_parameter("multi-thread"), &data, |b, data| { + let oxc_resolver = oxc_resolver_memory(); b.iter(|| { - let oxc_resolver = oxc_resolver_memory(); // Measure `Drop` performance. data.par_iter().for_each(|(path, request)| { _ = oxc_resolver.resolve(path, request); }); @@ -204,8 +213,8 @@ fn bench_resolver_memory(c: &mut Criterion) { BenchmarkId::from_parameter("resolve from symlinks"), &symlinks_range, |b, data| { + let oxc_resolver = oxc_resolver_memory(); b.iter(|| { - let oxc_resolver = oxc_resolver_memory(); // Measure `Drop` performance. for i in data.clone() { assert!( oxc_resolver.resolve(&symlink_test_dir, &format!("./file{i}")).is_ok(), @@ -238,8 +247,8 @@ fn bench_resolver_real(c: &mut Criterion) { let mut group = c.benchmark_group("resolver_real"); group.bench_with_input(BenchmarkId::from_parameter("single-thread"), &data, |b, data| { + let oxc_resolver = oxc_resolver_real(); b.iter(|| { - let oxc_resolver = oxc_resolver_real(); // Measure `Drop` performance. for (path, request) in data { _ = oxc_resolver.resolve(path, request); } @@ -247,8 +256,8 @@ fn bench_resolver_real(c: &mut Criterion) { }); group.bench_with_input(BenchmarkId::from_parameter("multi-thread"), &data, |b, data| { + let oxc_resolver = oxc_resolver_real(); b.iter(|| { - let oxc_resolver = oxc_resolver_real(); // Measure `Drop` performance. data.par_iter().for_each(|(path, request)| { _ = oxc_resolver.resolve(path, request); }); @@ -259,8 +268,8 @@ fn bench_resolver_real(c: &mut Criterion) { BenchmarkId::from_parameter("resolve from symlinks"), &symlinks_range, |b, data| { + let oxc_resolver = oxc_resolver_real(); b.iter(|| { - let oxc_resolver = oxc_resolver_real(); // Measure `Drop` performance. for i in data.clone() { assert!( oxc_resolver.resolve(&symlink_test_dir, &format!("./file{i}")).is_ok(), From e9c472c7c19281ac3ddf036fd529720ba8b98d9d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Nov 2025 00:01:07 +0000 Subject: [PATCH 03/17] chore(deps): update crate-ci/typos action to v1.39.2 (#833) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [crate-ci/typos](https://redirect.github.com/crate-ci/typos) | action | patch | `v1.39.1` -> `v1.39.2` | --- ### Release Notes
crate-ci/typos (crate-ci/typos) ### [`v1.39.2`](https://redirect.github.com/crate-ci/typos/blob/HEAD/CHANGELOG.md#014---2019-11-03) [Compare Source](https://redirect.github.com/crate-ci/typos/compare/v1.39.1...v1.39.2) ##### Bug Fixes - Ignore numbers as identifiers ([a00831c8](https://redirect.github.com/crate-ci/typos/commit/a00831c847b7efd81be520ea9b5d02f70555351f)) - Improve the organization of --help ([a48a457c](https://redirect.github.com/crate-ci/typos/commit/a48a457cc3ca817850118e2a2fb8b20fecdd40b8)) ##### Features - Dump files, identifiers, and words ([ce365ae1](https://redirect.github.com/crate-ci/typos/commit/ce365ae12e12fddfb6fc42a7f1e5ea71834d6051), closes [#​41](https://redirect.github.com/crate-ci/typos/issues/41)) - Give control over allowed identifier characters for leading vs rest ([107308a6](https://redirect.github.com/crate-ci/typos/commit/107308a655a425eb593bf5e4928572c16e6a9bdd)) ##### Performance - Use standard identifier rules to avoid doing umber checks ([107308a6](https://redirect.github.com/crate-ci/typos/commit/107308a655a425eb593bf5e4928572c16e6a9bdd)) - Only do hex check if digits are in identifiers ([68cd36d0](https://redirect.github.com/crate-ci/typos/commit/68cd36d0de90226dbc9d31c2ce6d8bf6b69adb5c)) [Unreleased]: https://redirect.github.com/crate-ci/typos/compare/v1.39.2...HEAD [1.39.2]: https://redirect.github.com/crate-ci/typos/compare/v1.39.1...v1.39.2 [1.39.1]: https://redirect.github.com/crate-ci/typos/compare/v1.39.0...v1.39.1 [1.39.0]: https://redirect.github.com/crate-ci/typos/compare/v1.38.1...v1.39.0 [1.38.1]: https://redirect.github.com/crate-ci/typos/compare/v1.38.0...v1.38.1 [1.38.0]: https://redirect.github.com/crate-ci/typos/compare/v1.37.3...v1.38.0 [1.37.3]: https://redirect.github.com/crate-ci/typos/compare/v1.37.2...v1.37.3 [1.37.2]: https://redirect.github.com/crate-ci/typos/compare/v1.37.1...v1.37.2 [1.37.1]: https://redirect.github.com/crate-ci/typos/compare/v1.37.0...v1.37.1 [1.37.0]: https://redirect.github.com/crate-ci/typos/compare/v1.36.3...v1.37.0 [1.36.3]: https://redirect.github.com/crate-ci/typos/compare/v1.36.2...v1.36.3 [1.36.2]: https://redirect.github.com/crate-ci/typos/compare/v1.36.1...v1.36.2 [1.36.1]: https://redirect.github.com/crate-ci/typos/compare/v1.36.0...v1.36.1 [1.36.0]: https://redirect.github.com/crate-ci/typos/compare/v1.35.8...v1.36.0 [1.35.8]: https://redirect.github.com/crate-ci/typos/compare/v1.35.7...v1.35.8 [1.35.7]: https://redirect.github.com/crate-ci/typos/compare/v1.35.6...v1.35.7 [1.35.6]: https://redirect.github.com/crate-ci/typos/compare/v1.35.5...v1.35.6 [1.35.5]: https://redirect.github.com/crate-ci/typos/compare/v1.35.4...v1.35.5 [1.35.4]: https://redirect.github.com/crate-ci/typos/compare/v1.35.3...v1.35.4 [1.35.3]: https://redirect.github.com/crate-ci/typos/compare/v1.35.2...v1.35.3 [1.35.2]: https://redirect.github.com/crate-ci/typos/compare/v1.35.1...v1.35.2 [1.35.1]: https://redirect.github.com/crate-ci/typos/compare/v1.35.0...v1.35.1 [1.35.0]: https://redirect.github.com/crate-ci/typos/compare/v1.34.0...v1.35.0 [1.34.0]: https://redirect.github.com/crate-ci/typos/compare/v1.33.1...v1.34.0 [1.33.1]: https://redirect.github.com/crate-ci/typos/compare/v1.33.0...v1.33.1 [1.33.0]: https://redirect.github.com/crate-ci/typos/compare/v1.32.0...v1.33.0 [1.32.0]: https://redirect.github.com/crate-ci/typos/compare/v1.31.2...v1.32.0 [1.31.2]: https://redirect.github.com/crate-ci/typos/compare/v1.31.1...v1.31.2 [1.31.1]: https://redirect.github.com/crate-ci/typos/compare/v1.31.0...v1.31.1 [1.31.0]: https://redirect.github.com/crate-ci/typos/compare/v1.30.3...v1.31.0 [1.30.3]: https://redirect.github.com/crate-ci/typos/compare/v1.30.2...v1.30.3 [1.30.2]: https://redirect.github.com/crate-ci/typos/compare/v1.30.1...v1.30.2 [1.30.1]: https://redirect.github.com/crate-ci/typos/compare/v1.30.0...v1.30.1 [1.30.0]: https://redirect.github.com/crate-ci/typos/compare/v1.29.10...v1.30.0 [1.29.10]: https://redirect.github.com/crate-ci/typos/compare/v1.29.9...v1.29.10 [1.29.9]: https://redirect.github.com/crate-ci/typos/compare/v1.29.8...v1.29.9 [1.29.8]: https://redirect.github.com/crate-ci/typos/compare/v1.29.7...v1.29.8 [1.29.7]: https://redirect.github.com/crate-ci/typos/compare/v1.29.6...v1.29.7 [1.29.6]: https://redirect.github.com/crate-ci/typos/compare/v1.29.5...v1.29.6 [1.29.5]: https://redirect.github.com/crate-ci/typos/compare/v1.29.4...v1.29.5 [1.29.4]: https://redirect.github.com/crate-ci/typos/compare/v1.29.3...v1.29.4 [1.29.3]: https://redirect.github.com/crate-ci/typos/compare/v1.29.2...v1.29.3 [1.29.2]: https://redirect.github.com/crate-ci/typos/compare/v1.29.1...v1.29.2 [1.29.1]: https://redirect.github.com/crate-ci/typos/compare/v1.29.0...v1.29.1 [1.29.0]: https://redirect.github.com/crate-ci/typos/compare/v1.28.4...v1.29.0 [1.28.4]: https://redirect.github.com/crate-ci/typos/compare/v1.28.3...v1.28.4 [1.28.3]: https://redirect.github.com/crate-ci/typos/compare/v1.28.2...v1.28.3 [1.28.2]: https://redirect.github.com/crate-ci/typos/compare/v1.28.1...v1.28.2 [1.28.1]: https://redirect.github.com/crate-ci/typos/compare/v1.28.0...v1.28.1 [1.28.0]: https://redirect.github.com/crate-ci/typos/compare/v1.27.3...v1.28.0 [1.27.3]: https://redirect.github.com/crate-ci/typos/compare/v1.27.2...v1.27.3 [1.27.2]: https://redirect.github.com/crate-ci/typos/compare/v1.27.1...v1.27.2 [1.27.1]: https://redirect.github.com/crate-ci/typos/compare/v1.27.0...v1.27.1 [1.27.0]: https://redirect.github.com/crate-ci/typos/compare/v1.26.8...v1.27.0 [1.26.8]: https://redirect.github.com/crate-ci/typos/compare/v1.26.7...v1.26.8 [1.26.7]: https://redirect.github.com/crate-ci/typos/compare/v1.26.6...v1.26.7 [1.26.6]: https://redirect.github.com/crate-ci/typos/compare/v1.26.5...v1.26.6 [1.26.5]: https://redirect.github.com/crate-ci/typos/compare/v1.26.4...v1.26.5 [1.26.4]: https://redirect.github.com/crate-ci/typos/compare/v1.26.3...v1.26.4 [1.26.3]: https://redirect.github.com/crate-ci/typos/compare/v1.26.2...v1.26.3 [1.26.2]: https://redirect.github.com/crate-ci/typos/compare/v1.26.1...v1.26.2 [1.26.1]: https://redirect.github.com/crate-ci/typos/compare/v1.26.0...v1.26.1 [1.26.0]: https://redirect.github.com/crate-ci/typos/compare/v1.25.0...v1.26.0 [1.25.0]: https://redirect.github.com/crate-ci/typos/compare/v1.24.6...v1.25.0 [1.24.6]: https://redirect.github.com/crate-ci/typos/compare/v1.24.5...v1.24.6 [1.24.5]: https://redirect.github.com/crate-ci/typos/compare/v1.24.4...v1.24.5 [1.24.4]: https://redirect.github.com/crate-ci/typos/compare/v1.24.3...v1.24.4 [1.24.3]: https://redirect.github.com/crate-ci/typos/compare/v1.24.2...v1.24.3 [1.24.2]: https://redirect.github.com/crate-ci/typos/compare/v1.24.1...v1.24.2 [1.24.1]: https://redirect.github.com/crate-ci/typos/compare/v1.24.0...v1.24.1 [1.24.0]: https://redirect.github.com/crate-ci/typos/compare/v1.23.7...v1.24.0 [1.23.7]: https://redirect.github.com/crate-ci/typos/compare/v1.23.6...v1.23.7 [1.23.6]: https://redirect.github.com/crate-ci/typos/compare/v1.23.5...v1.23.6 [1.23.5]: https://redirect.github.com/crate-ci/typos/compare/v1.23.4...v1.23.5 [1.23.4]: https://redirect.github.com/crate-ci/typos/compare/v1.23.3...v1.23.4 [1.23.3]: https://redirect.github.com/crate-ci/typos/compare/v1.23.2...v1.23.3 [1.23.2]: https://redirect.github.com/crate-ci/typos/compare/v1.23.1...v1.23.2 [1.23.1]: https://redirect.github.com/crate-ci/typos/compare/v1.23.0...v1.23.1 [1.23.0]: https://redirect.github.com/crate-ci/typos/compare/v1.22.9...v1.23.0 [1.22.9]: https://redirect.github.com/crate-ci/typos/compare/v1.22.8...v1.22.9 [1.22.8]: https://redirect.github.com/crate-ci/typos/compare/v1.22.7...v1.22.8 [1.22.7]: https://redirect.github.com/crate-ci/typos/compare/v1.22.6...v1.22.7 [1.22.6]: https://redirect.github.com/crate-ci/typos/compare/v1.22.5...v1.22.6 [1.22.5]: https://redirect.github.com/crate-ci/typos/compare/v1.22.4...v1.22.5 [1.22.4]: https://redirect.github.com/crate-ci/typos/compare/v1.22.3...v1.22.4 [1.22.3]: https://redirect.github.com/crate-ci/typos/compare/v1.22.2...v1.22.3 [1.22.2]: https://redirect.github.com/crate-ci/typos/compare/v1.22.1...v1.22.2 [1.22.1]: https://redirect.github.com/crate-ci/typos/compare/v1.22.0...v1.22.1 [1.22.0]: https://redirect.github.com/crate-ci/typos/compare/v1.21.0...v1.22.0 [1.21.0]: https://redirect.github.com/crate-ci/typos/compare/v1.20.10...v1.21.0 [1.20.10]: https://redirect.github.com/crate-ci/typos/compare/v1.20.9...v1.20.10 [1.20.9]: https://redirect.github.com/crate-ci/typos/compare/v1.20.8...v1.20.9 [1.20.8]: https://redirect.github.com/crate-ci/typos/compare/v1.20.7...v1.20.8 [1.20.7]: https://redirect.github.com/crate-ci/typos/compare/v1.20.6...v1.20.7 [1.20.6]: https://redirect.github.com/crate-ci/typos/compare/v1.20.5...v1.20.6 [1.20.5]: https://redirect.github.com/crate-ci/typos/compare/v1.20.4...v1.20.5 [1.20.4]: https://redirect.github.com/crate-ci/typos/compare/v1.20.3...v1.20.4 [1.20.3]: https://redirect.github.com/crate-ci/typos/compare/v1.20.2...v1.20.3 [1.20.2]: https://redirect.github.com/crate-ci/typos/compare/v1.20.1...v1.20.2 [1.20.1]: https://redirect.github.com/crate-ci/typos/compare/v1.20.0...v1.20.1 [1.20.0]: https://redirect.github.com/crate-ci/typos/compare/v1.19.0...v1.20.0 [1.19.0]: https://redirect.github.com/crate-ci/typos/compare/v1.18.2...v1.19.0 [1.18.2]: https://redirect.github.com/crate-ci/typos/compare/v1.18.1...v1.18.2 [1.18.1]: https://redirect.github.com/crate-ci/typos/compare/v1.18.0...v1.18.1 [1.18.0]: https://redirect.github.com/crate-ci/typos/compare/v1.17.2...v1.18.0 [1.17.2]: https://redirect.github.com/crate-ci/typos/compare/v1.17.1...v1.17.2 [1.17.1]: https://redirect.github.com/crate-ci/typos/compare/v1.17.0...v1.17.1 [1.17.0]: https://redirect.github.com/crate-ci/typos/compare/v1.16.26...v1.17.0 [1.16.26]: https://redirect.github.com/crate-ci/typos/compare/v1.16.25...v1.16.26 [1.16.25]: https://redirect.github.com/crate-ci/typos/compare/v1.16.24...v1.16.25 [1.16.24]: https://redirect.github.com/crate-ci/typos/compare/v1.16.23...v1.16.24 [1.16.23]: https://redirect.github.com/crate-ci/typos/compare/v1.16.22...v1.16.23 [1.16.22]: https://redirect.github.com/crate-ci/typos/compare/v1.16.21...v1.16.22 [1.16.21]: https://redirect.github.com/crate-ci/typos/compare/v1.16.20...v1.16.21 [1.16.20]: https://redirect.github.com/crate-ci/typos/compare/v1.16.19...v1.16.20 [1.16.19]: https://redirect.github.com/crate-ci/typos/compare/v1.16.18...v1.16.19 [1.16.18]: https://redirect.github.com/crate-ci/typos/compare/v1.16.17...v1.16.18 [1.16.17]: https://redirect.github.com/crate-ci/typos/compare/v1.16.16...v1.16.17 [1.16.16]: https://redirect.github.com/crate-ci/typos/compare/v1.16.15...v1.16.16 [1.16.15]: https://redirect.github.com/crate-ci/typos/compare/v1.16.14...v1.16.15 [1.16.14]: https://redirect.github.com/crate-ci/typos/compare/v1.16.13...v1.16.14 [1.16.13]: https://redirect.github.com/crate-ci/typos/compare/v1.16.12...v1.16.13 [1.16.12]: https://redirect.github.com/crate-ci/typos/compare/v1.16.11...v1.16.12 [1.16.11]: https://redirect.github.com/crate-ci/typos/compare/v1.16.10...v1.16.11 [1.16.10]: https://redirect.github.com/crate-ci/typos/compare/v1.16.9...v1.16.10 [1.16.9]: https://redirect.github.com/crate-ci/typos/compare/v1.16.8...v1.16.9 [1.16.8]: https://redirect.github.com/crate-ci/typos/compare/v1.16.7...v1.16.8 [1.16.7]: https://redirect.github.com/crate-ci/typos/compare/v1.16.6...v1.16.7 [1.16.6]: https://redirect.github.com/crate-ci/typos/compare/v1.16.5...v1.16.6 [1.16.5]: https://redirect.github.com/crate-ci/typos/compare/v1.16.4...v1.16.5 [1.16.4]: https://redirect.github.com/crate-ci/typos/compare/v1.16.3...v1.16.4 [1.16.3]: https://redirect.github.com/crate-ci/typos/compare/v1.16.2...v1.16.3 [1.16.2]: https://redirect.github.com/crate-ci/typos/compare/v1.16.1...v1.16.2 [1.16.1]: https://redirect.github.com/crate-ci/typos/compare/v1.16.0...v1.16.1 [1.16.0]: https://redirect.github.com/crate-ci/typos/compare/v1.15.10...v1.16.0 [1.15.10]: https://redirect.github.com/crate-ci/typos/compare/v1.15.9...v1.15.10 [1.15.9]: https://redirect.github.com/crate-ci/typos/compare/v1.15.8...v1.15.9 [1.15.8]: https://redirect.github.com/crate-ci/typos/compare/v1.15.7...v1.15.8 [1.15.7]: https://redirect.github.com/crate-ci/typos/compare/v1.15.6...v1.15.7 [1.15.6]: https://redirect.github.com/crate-ci/typos/compare/v1.15.5...v1.15.6 [1.15.5]: https://redirect.github.com/crate-ci/typos/compare/v1.15.4...v1.15.5 [1.15.4]: https://redirect.github.com/crate-ci/typos/compare/v1.15.3...v1.15.4 [1.15.3]: https://redirect.github.com/crate-ci/typos/compare/v1.15.2...v1.15.3 [1.15.2]: https://redirect.github.com/crate-ci/typos/compare/v1.15.1...v1.15.2 [1.15.1]: https://redirect.github.com/crate-ci/typos/compare/v1.15.0...v1.15.1 [1.15.0]: https://redirect.github.com/crate-ci/typos/compare/v1.14.12...v1.15.0 [1.14.12]: https://redirect.github.com/crate-ci/typos/compare/v1.14.11...v1.14.12 [1.14.11]: https://redirect.github.com/crate-ci/typos/compare/v1.14.10...v1.14.11 [1.14.10]: https://redirect.github.com/crate-ci/typos/compare/v1.14.9...v1.14.10 [1.14.9]: https://redirect.github.com/crate-ci/typos/compare/v1.14.8...v1.14.9 [1.14.8]: https://redirect.github.com/crate-ci/typos/compare/v1.14.7...v1.14.8 [1.14.7]: https://redirect.github.com/crate-ci/typos/compare/v1.14.6...v1.14.7 [1.14.6]: https://redirect.github.com/crate-ci/typos/compare/v1.14.5...v1.14.6 [1.14.5]: https://redirect.github.com/crate-ci/typos/compare/v1.14.4...v1.14.5 [1.14.4]: https://redirect.github.com/crate-ci/typos/compare/v1.14.3...v1.14.4 [1.14.3]: https://redirect.github.com/crate-ci/typos/compare/v1.14.2...v1.14.3 [1.14.2]: https://redirect.github.com/crate-ci/typos/compare/v1.14.1...v1.14.2 [1.14.1]: https://redirect.github.com/crate-ci/typos/compare/v1.14.0...v1.14.1 [1.14.0]: https://redirect.github.com/crate-ci/typos/compare/v1.13.26...v1.14.0 [1.13.26]: https://redirect.github.com/crate-ci/typos/compare/v1.13.25...v1.13.26 [1.13.25]: https://redirect.github.com/crate-ci/typos/compare/v1.13.24...v1.13.25 [1.13.24]: https://redirect.github.com/crate-ci/typos/compare/v1.13.23...v1.13.24 [1.13.23]: https://redirect.github.com/crate-ci/typos/compare/v1.13.22...v1.13.23 [1.13.22]: https://redirect.github.com/crate-ci/typos/compare/v1.13.21...v1.13.22 [1.13.21]: https://redirect.github.com/crate-ci/typos/compare/v1.13.20...v1.13.21 [1.13.20]: https://redirect.github.com/crate-ci/typos/compare/v1.13.19...v1.13.20 [1.13.19]: https://redirect.github.com/crate-ci/typos/compare/v1.13.18...v1.13.19 [1.13.18]: https://redirect.github.com/crate-ci/typos/compare/v1.13.17...v1.13.18 [1.13.17]: https://redirect.github.com/crate-ci/typos/compare/v1.13.16...v1.13.17 [1.13.16]: https://redirect.github.com/crate-ci/typos/compare/v1.13.15...v1.13.16 [1.13.15]: https://redirect.github.com/crate-ci/typos/compare/v1.13.14...v1.13.15 [1.13.14]: https://redirect.github.com/crate-ci/typos/compare/v1.13.13...v1.13.14 [1.13.13]: https://redirect.github.com/crate-ci/typos/compare/v1.13.12...v1.13.13 [1.13.12]: https://redirect.github.com/crate-ci/typos/compare/v1.13.11...v1.13.12 [1.13.11]: https://redirect.github.com/crate-ci/typos/compare/v1.13.10...v1.13.11 [1.13.10]: https://redirect.github.com/crate-ci/typos/compare/v1.13.9...v1.13.10 [1.13.9]: https://redirect.github.com/crate-ci/typos/compare/v1.13.8...v1.13.9 [1.13.8]: https://redirect.github.com/crate-ci/typos/compare/v1.13.7...v1.13.8 [1.13.7]: https://redirect.github.com/crate-ci/typos/compare/v1.13.6...v1.13.7 [1.13.6]: https://redirect.github.com/crate-ci/typos/compare/v1.13.5...v1.13.6 [1.13.5]: https://redirect.github.com/crate-ci/typos/compare/v1.13.4...v1.13.5 [1.13.4]: https://redirect.github.com/crate-ci/typos/compare/v1.13.3...v1.13.4 [1.13.3]: https://redirect.github.com/crate-ci/typos/compare/v1.13.2...v1.13.3 [1.13.2]: https://redirect.github.com/crate-ci/typos/compare/v1.13.1...v1.13.2 [1.13.1]: https://redirect.github.com/crate-ci/typos/compare/v1.13.0...v1.13.1 [1.13.0]: https://redirect.github.com/crate-ci/typos/compare/v1.12.14...v1.13.0 [1.12.14]: https://redirect.github.com/crate-ci/typos/compare/v1.12.13...v1.12.14 [1.12.13]: https://redirect.github.com/crate-ci/typos/compare/v1.12.12...v1.12.13 [1.12.12]: https://redirect.github.com/crate-ci/typos/compare/v1.12.11...v1.12.12 [1.12.11]: https://redirect.github.com/crate-ci/typos/compare/v1.12.10...v1.12.11 [1.12.10]: https://redirect.github.com/crate-ci/typos/compare/v1.12.9...v1.12.10 [1.12.9]: https://redirect.github.com/crate-ci/typos/compare/v1.12.8...v1.12.9 [1.12.8]: https://redirect.github.com/crate-ci/typos/compare/v1.12.7...v1.12.8 [1.12.7]: https://redirect.github.com/crate-ci/typos/compare/v1.12.6...v1.12.7 [1.12.6]: https://redirect.github.com/crate-ci/typos/compare/v1.12.5...v1.12.6 [1.12.5]: https://redirect.github.com/crate-ci/typos/compare/v1.12.4...v1.12.5 [1.12.4]: https://redirect.github.com/crate-ci/typos/compare/v1.12.3...v1.12.4 [1.12.3]: https://redirect.github.com/crate-ci/typos/compare/v1.12.2...v1.12.3 [1.12.2]: https://redirect.github.com/crate-ci/typos/compare/v1.12.1...v1.12.2 [1.12.1]: https://redirect.github.com/crate-ci/typos/compare/v1.12.0...v1.12.1 [1.12.0]: https://redirect.github.com/crate-ci/typos/compare/v1.11.5...v1.12.0 [1.11.5]: https://redirect.github.com/crate-ci/typos/compare/v1.11.4...v1.11.5 [1.11.4]: https://redirect.github.com/crate-ci/typos/compare/v1.11.3...v1.11.4 [1.11.3]: https://redirect.github.com/crate-ci/typos/compare/v1.11.2...v1.11.3 [1.11.2]: https://redirect.github.com/crate-ci/typos/compare/v1.11.1...v1.11.2 [1.11.1]: https://redirect.github.com/crate-ci/typos/compare/v1.11.0...v1.11.1 [1.11.0]: https://redirect.github.com/crate-ci/typos/compare/v1.10.3...v1.11.0 [1.10.3]: https://redirect.github.com/crate-ci/typos/compare/v1.10.2...v1.10.3 [1.10.2]: https://redirect.github.com/crate-ci/typos/compare/v1.10.1...v1.10.2 [1.10.1]: https://redirect.github.com/crate-ci/typos/compare/v1.10.0...v1.10.1 [1.10.0]: https://redirect.github.com/crate-ci/typos/compare/v1.9.0...v1.10.0 [1.9.0]: https://redirect.github.com/crate-ci/typos/compare/v1.8.1...v1.9.0 [1.8.1]: https://redirect.github.com/crate-ci/typos/compare/v1.8.0...v1.8.1 [1.8.0]: https://redirect.github.com/crate-ci/typos/compare/v1.7.3...v1.8.0 [1.7.3]: https://redirect.github.com/crate-ci/typos/compare/v1.7.2...v1.7.3 [1.7.2]: https://redirect.github.com/crate-ci/typos/compare/v1.7.1...v1.7.2 [1.7.1]: https://redirect.github.com/crate-ci/typos/compare/v1.7.0...v1.7.1 [1.7.0]: https://redirect.github.com/crate-ci/typos/compare/v1.6.0...v1.7.0 [1.6.0]: https://redirect.github.com/crate-ci/typos/compare/v1.5.0...v1.6.0 [1.5.0]: https://redirect.github.com/crate-ci/typos/compare/v1.4.1...v1.5.0 [1.4.1]: https://redirect.github.com/crate-ci/typos/compare/v1.4.0...v1.4.1 [1.4.0]: https://redirect.github.com/crate-ci/typos/compare/v1.3.9...v1.4.0 [1.3.9]: https://redirect.github.com/crate-ci/typos/compare/v1.3.8...v1.3.9 [1.3.8]: https://redirect.github.com/crate-ci/typos/compare/v1.3.7...v1.3.8 [1.3.7]: https://redirect.github.com/crate-ci/typos/compare/v1.3.6...v1.3.7 [1.3.6]: https://redirect.github.com/crate-ci/typos/compare/v1.3.5...v1.3.6 [1.3.5]: https://redirect.github.com/crate-ci/typos/compare/v1.3.4...v1.3.5 [1.3.4]: https://redirect.github.com/crate-ci/typos/compare/v1.3.3...v1.3.4 [1.3.3]: https://redirect.github.com/crate-ci/typos/compare/v1.3.2...v1.3.3 [1.3.2]: https://redirect.github.com/crate-ci/typos/compare/v1.3.1...v1.3.2 [1.3.1]: https://redirect.github.com/crate-ci/typos/compare/v1.3.0...v1.3.1 [1.3.0]: https://redirect.github.com/crate-ci/typos/compare/v1.2.1...v1.3.0 [1.2.1]: https://redirect.github.com/crate-ci/typos/compare/v1.2.0...v1.2.1 [1.2.0]: https://redirect.github.com/crate-ci/typos/compare/v1.1.9...v1.2.0 [1.1.9]: https://redirect.github.com/crate-ci/typos/compare/v1.1.8...v1.1.9 [1.1.8]: https://redirect.github.com/crate-ci/typos/compare/v1.1.7...v1.1.8 [1.1.7]: https://redirect.github.com/crate-ci/typos/compare/v1.1.6...v1.1.7 [1.1.6]: https://redirect.github.com/crate-ci/typos/compare/v1.1.5...v1.1.6 [1.1.5]: https://redirect.github.com/crate-ci/typos/compare/v1.1.4...v1.1.5 [1.1.4]: https://redirect.github.com/crate-ci/typos/compare/v1.1.3...v1.1.4 [1.1.3]: https://redirect.github.com/crate-ci/typos/compare/v1.1.2...v1.1.3 [1.1.2]: https://redirect.github.com/crate-ci/typos/compare/v1.1.1...v1.1.2 [1.1.1]: https://redirect.github.com/crate-ci/typos/compare/v1.1.0...v1.1.1 [1.1.0]: https://redirect.github.com/crate-ci/typos/compare/v1.0.11...v1.1.0 [1.0.11]: https://redirect.github.com/crate-ci/typos/compare/v1.0.10...v1.0.11 [1.0.10]: https://redirect.github.com/crate-ci/typos/compare/v1.0.9...v1.0.10 [1.0.9]: https://redirect.github.com/crate-ci/typos/compare/v1.0.8...v1.0.9 [1.0.8]: https://redirect.github.com/crate-ci/typos/compare/v1.0.7...v1.0.8 [1.0.7]: https://redirect.github.com/crate-ci/typos/compare/v1.0.6...v1.0.7 [1.0.6]: https://redirect.github.com/crate-ci/typos/compare/v1.0.5...v1.0.6 [1.0.5]: https://redirect.github.com/crate-ci/typos/compare/v1.0.4...v1.0.5 [1.0.4]: https://redirect.github.com/crate-ci/typos/compare/v1.0.3...v1.0.4 [1.0.3]: https://redirect.github.com/crate-ci/typos/compare/v1.0.2...v1.0.3 [1.0.2]: https://redirect.github.com/crate-ci/typos/compare/v1.0.1...v1.0.2 [1.0.1]: https://redirect.github.com/crate-ci/typos/compare/v1.0.0...v1.0.1 [1.0.0]: https://redirect.github.com/crate-ci/typos/compare/v0.4.0...v1.0.0 [0.4.0]: https://redirect.github.com/crate-ci/typos/compare/v0.3.0...v0.4.0 [0.3.0]: https://redirect.github.com/crate-ci/typos/compare/v0.2.0...v0.3.0 [0.2.0]: https://redirect.github.com/crate-ci/typos/compare/v0.1.4...v0.2.0
--- ### 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. --- - [ ] 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-resolver). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23ceb9d0..44783910 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,7 +76,7 @@ jobs: components: clippy rust-docs - run: cargo clippy --all-features --all-targets -- -D warnings - run: RUSTDOCFLAGS='-D warnings' cargo doc --no-deps --all-features - - uses: crate-ci/typos@1af53e3774f068183ffd0c7193eb061a2b65a531 # v1.39.1 + - uses: crate-ci/typos@626c4bedb751ce0b7f03262ca97ddda9a076ae1c # v1.39.2 with: files: . From 06c2c4568fc19f585b74f37b09f7f48685a6f95b Mon Sep 17 00:00:00 2001 From: Boshen Date: Sun, 16 Nov 2025 09:27:48 +0000 Subject: [PATCH 04/17] refactor: remove CachedPathImpl::canonicaling (#834) --- src/cache/cache_impl.rs | 58 +++++++++++++++++++++++++-------------- src/cache/cached_path.rs | 8 ++---- src/cache/thread_local.rs | 9 +----- 3 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/cache/cache_impl.rs b/src/cache/cache_impl.rs index 9a45117b..57d11518 100644 --- a/src/cache/cache_impl.rs +++ b/src/cache/cache_impl.rs @@ -1,9 +1,10 @@ use std::{ borrow::Cow, + collections::HashSet as StdHashSet, hash::{BuildHasherDefault, Hash, Hasher}, io, path::{Path, PathBuf}, - sync::{Arc, atomic::Ordering}, + sync::Arc, }; use cfg_if::cfg_if; @@ -15,7 +16,6 @@ use rustc_hash::FxHasher; use super::borrowed_path::BorrowedCachedPath; use super::cached_path::{CachedPath, CachedPathImpl}; use super::hasher::IdentityHasher; -use super::thread_local::THREAD_ID; use crate::{ FileSystem, PackageJson, ResolveError, ResolveOptions, TsConfig, context::ResolveContext as Ctx, path::PathUtil, @@ -225,36 +225,54 @@ impl Cache { /// /// pub(crate) fn canonicalize_impl(&self, path: &CachedPath) -> Result { - // Check if this thread is already canonicalizing. If so, we have found a circular symlink. - // If a different thread is canonicalizing, OnceLock will queue this thread to wait for the result. - let tid = THREAD_ID.with(|t| *t); - if path.canonicalizing.load(Ordering::Acquire) == tid { - return Err(io::Error::new(io::ErrorKind::NotFound, "Circular symlink").into()); - } + // Use get_or_init to allow multiple threads to safely canonicalize the same path. + // Only one thread will perform the actual canonicalization, others will wait for the result. + // The Result is stored inside the OnceLock to cache both success and failure cases. + let result = path.canonicalized.get_or_init(|| { + // Each canonicalization chain gets its own visited set for circular symlink detection + let mut visited = StdHashSet::new(); + self.canonicalize_with_visited(path, &mut visited).map(|cp| Arc::downgrade(&cp.0)) + }); - let mut canonicalized_guard = path.canonicalized.lock().unwrap(); - let canonicalized = canonicalized_guard.clone()?; - if let Some(cached_path) = canonicalized.upgrade() { - return Ok(CachedPath(cached_path)); - } + result.as_ref().map_err(Clone::clone).and_then(|weak| { + weak.upgrade().map(CachedPath).ok_or_else(|| { + io::Error::new(io::ErrorKind::NotFound, "Path no longer exists").into() + }) + }) + } - path.canonicalizing.store(tid, Ordering::Release); + /// Internal helper for canonicalization with circular symlink detection. + fn canonicalize_with_visited( + &self, + path: &CachedPath, + visited: &mut StdHashSet, + ) -> Result { + // Check for circular symlink by tracking visited paths in the current canonicalization chain + if !visited.insert(path.hash) { + return Err(io::Error::new(io::ErrorKind::NotFound, "Circular symlink").into()); + } let res = path.parent().map_or_else( || Ok(path.normalize_root(self)), |parent| { - self.canonicalize_impl(&parent).and_then(|parent_canonical| { + self.canonicalize_with_visited(&parent, visited).and_then(|parent_canonical| { let normalized = parent_canonical .normalize_with(path.path().strip_prefix(parent.path()).unwrap(), self); if self.fs.symlink_metadata(path.path()).is_ok_and(|m| m.is_symlink) { let link = self.fs.read_link(normalized.path())?; if link.is_absolute() { - return self.canonicalize_impl(&self.value(&link.normalize())); + return self.canonicalize_with_visited( + &self.value(&link.normalize()), + visited, + ); } else if let Some(dir) = normalized.parent() { // Symlink is relative `../../foo.js`, use the path directory // to resolve this symlink. - return self.canonicalize_impl(&dir.normalize_with(&link, self)); + return self.canonicalize_with_visited( + &dir.normalize_with(&link, self), + visited, + ); } debug_assert!( false, @@ -268,10 +286,8 @@ impl Cache { }, ); - path.canonicalizing.store(0, Ordering::Release); - // Convert to Weak reference for storage - *canonicalized_guard = res.as_ref().map_err(Clone::clone).map(|cp| Arc::downgrade(&cp.0)); - + // Remove from visited set when unwinding the recursion + visited.remove(&path.hash); res } } diff --git a/src/cache/cached_path.rs b/src/cache/cached_path.rs index af676545..8356de01 100644 --- a/src/cache/cached_path.rs +++ b/src/cache/cached_path.rs @@ -4,7 +4,7 @@ use std::{ hash::{Hash, Hasher}, ops::Deref, path::{Component, Path, PathBuf}, - sync::{Arc, Mutex, Weak, atomic::AtomicU64}, + sync::{Arc, Weak}, }; use cfg_if::cfg_if; @@ -27,8 +27,7 @@ pub struct CachedPathImpl { pub is_node_modules: bool, pub inside_node_modules: bool, pub meta: OnceLock>, - pub canonicalized: Mutex, ResolveError>>, - pub canonicalizing: AtomicU64, + pub canonicalized: OnceLock, ResolveError>>, pub node_modules: OnceLock>>, pub package_json: OnceLock>>, pub tsconfig: OnceLock>>, @@ -49,8 +48,7 @@ impl CachedPathImpl { is_node_modules, inside_node_modules, meta: OnceLock::new(), - canonicalized: Mutex::new(Ok(Weak::new())), - canonicalizing: AtomicU64::new(0), + canonicalized: OnceLock::new(), node_modules: OnceLock::new(), package_json: OnceLock::new(), tsconfig: OnceLock::new(), diff --git a/src/cache/thread_local.rs b/src/cache/thread_local.rs index 7c8c7c9d..70607845 100644 --- a/src/cache/thread_local.rs +++ b/src/cache/thread_local.rs @@ -1,14 +1,7 @@ -use std::{ - cell::RefCell, - path::PathBuf, - sync::atomic::{AtomicU64, Ordering}, -}; - -static THREAD_COUNT: AtomicU64 = AtomicU64::new(1); +use std::{cell::RefCell, path::PathBuf}; thread_local! { /// Per-thread pre-allocated path that is used to perform operations on paths more quickly. /// Learned from parcel pub static SCRATCH_PATH: RefCell = RefCell::new(PathBuf::with_capacity(256)); - pub static THREAD_ID: u64 = THREAD_COUNT.fetch_add(1, Ordering::SeqCst); } From 31ed0e0fe70cfb551a3dc2896a05ec1500c65b29 Mon Sep 17 00:00:00 2001 From: Boshen Date: Sun, 16 Nov 2025 09:27:48 +0000 Subject: [PATCH 05/17] fix: use std::fs::canonicalize as a fallback when canonicalize fails (#835) --- benches/resolver.rs | 28 ++++++++++++++++++++++++++++ src/cache/cache_impl.rs | 13 ++++++++++--- src/file_system.rs | 30 ++++++++++++++++++++++++++++++ src/tests/memory_fs.rs | 9 +++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/benches/resolver.rs b/benches/resolver.rs index ac56c0ba..f5aa12e5 100644 --- a/benches/resolver.rs +++ b/benches/resolver.rs @@ -716,5 +716,33 @@ mod memory_fs { )) }) } + + fn canonicalize(&self, path: &Path) -> io::Result { + // Follow symlinks to resolve the canonical path + let mut current = path.to_path_buf(); + let mut visited = FxHashSet::default(); + + while let Some(target) = self.symlinks.get(¤t) { + if !visited.insert(current.clone()) { + return Err(io::Error::other("Circular symlink")); + } + + current = if target.is_relative() { + current.parent().unwrap().join(target) + } else { + target.clone() + }; + } + + // Verify the final path exists + if self.files.contains_key(¤t) || self.directories.contains(¤t) { + Ok(current) + } else { + Err(io::Error::new( + io::ErrorKind::NotFound, + format!("Path not found: {}", path.display()), + )) + } + } } } diff --git a/src/cache/cache_impl.rs b/src/cache/cache_impl.rs index 57d11518..4c5784ca 100644 --- a/src/cache/cache_impl.rs +++ b/src/cache/cache_impl.rs @@ -235,9 +235,16 @@ impl Cache { }); result.as_ref().map_err(Clone::clone).and_then(|weak| { - weak.upgrade().map(CachedPath).ok_or_else(|| { - io::Error::new(io::ErrorKind::NotFound, "Path no longer exists").into() - }) + weak.upgrade() + .map(CachedPath) + .or_else(|| { + // Cache was cleared while canonicalizing. Fall back to direct FS canonicalize + // without caching the result to ensure we still return the resolved path. + self.fs.canonicalize(path.path()).ok().map(|canonical| self.value(&canonical)) + }) + .ok_or_else(|| { + io::Error::new(io::ErrorKind::NotFound, "Path no longer exists").into() + }) }) } diff --git a/src/file_system.rs b/src/file_system.rs index 0fde005b..44043a59 100644 --- a/src/file_system.rs +++ b/src/file_system.rs @@ -64,6 +64,13 @@ pub trait FileSystem: Send + Sync { /// /// See [std::fs::read_link] fn read_link(&self, path: &Path) -> Result; + + /// Returns the canonical, absolute form of a path with all intermediate components normalized. + /// + /// # Errors + /// + /// See [std::fs::canonicalize] + fn canonicalize(&self, path: &Path) -> io::Result; } /// Metadata information about a file @@ -208,6 +215,14 @@ impl FileSystemOs { } } } + + /// # Errors + /// + /// See [std::fs::canonicalize] + #[inline] + pub fn canonicalize(path: &Path) -> io::Result { + fs::canonicalize(path) + } } impl FileSystem for FileSystemOs { @@ -281,6 +296,21 @@ impl FileSystem for FileSystemOs { } Self::read_link(path) } + + fn canonicalize(&self, path: &Path) -> io::Result { + cfg_if! { + if #[cfg(feature = "yarn_pnp")] { + if self.yarn_pnp { + return match VPath::from(path)? { + VPath::Zip(info) => Self::canonicalize(&info.physical_base_path().join(info.zip_path)), + VPath::Virtual(info) => Self::canonicalize(&info.physical_base_path()), + VPath::Native(path) => Self::canonicalize(&path), + } + } + } + } + Self::canonicalize(path) + } } #[test] diff --git a/src/tests/memory_fs.rs b/src/tests/memory_fs.rs index 6044d8a6..b0be28f6 100644 --- a/src/tests/memory_fs.rs +++ b/src/tests/memory_fs.rs @@ -86,4 +86,13 @@ impl FileSystem for MemoryFS { fn read_link(&self, _path: &Path) -> Result { Err(io::Error::new(io::ErrorKind::NotFound, "not a symlink").into()) } + + fn canonicalize(&self, path: &Path) -> io::Result { + // MemoryFS doesn't support symlinks, so just verify path exists and return it + use vfs::FileSystem; + self.fs + .metadata(path.to_string_lossy().as_ref()) + .map_err(|err| io::Error::new(io::ErrorKind::NotFound, err))?; + Ok(path.to_path_buf()) + } } From 5a42e31a431158f93fe40594c29ee88d8b992784 Mon Sep 17 00:00:00 2001 From: Boshen Date: Sun, 16 Nov 2025 10:24:49 +0000 Subject: [PATCH 06/17] feat: add many.rs example for profiling resolver with many packages (#836) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Adds a new example `examples/many.rs` for profiling the resolver with many package resolution requests. The example: - Walks the `node_modules` directory from the current working directory - Collects all package names (regular and scoped packages) - Filters out `@types` packages and dot directories (`.bin`, `.cache`, etc.) - Resolves each package using the resolver with ESM/browser configuration - Prints summary statistics (total packages, successful/failed resolutions) ## Usage ```bash cargo run --example many ``` This is useful for profiling resolver performance with realistic workloads. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- examples/many.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 examples/many.rs diff --git a/examples/many.rs b/examples/many.rs new file mode 100644 index 00000000..da5690b3 --- /dev/null +++ b/examples/many.rs @@ -0,0 +1,69 @@ +use std::{env, fs}; + +use rayon::prelude::*; + +use oxc_resolver::{ResolveOptions, Resolver}; + +fn main() { + let cwd = env::current_dir().expect("Failed to get current directory"); + let node_modules = cwd.join("node_modules"); + + if !node_modules.exists() { + eprintln!("node_modules directory not found at {}", node_modules.display()); + return; + } + + // Collect all package names + let mut packages = Vec::new(); + + let entries = fs::read_dir(&node_modules).expect("Failed to read node_modules directory"); + + for entry in entries.filter_map(Result::ok) { + let path = entry.path(); + if !path.is_dir() { + continue; + } + + let dir_name = path.file_name().unwrap().to_string_lossy(); + + // Skip dot directories + if dir_name.starts_with('.') { + continue; + } + + if dir_name.starts_with('@') { + // Skip @types packages + if dir_name == "@types" { + continue; + } + // Scoped package - read subdirectories + if let Ok(scope_entries) = fs::read_dir(&path) { + for scope_entry in scope_entries.filter_map(Result::ok) { + let scope_path = scope_entry.path(); + if scope_path.is_dir() { + let package_name = scope_path.file_name().unwrap().to_string_lossy(); + packages.push(format!("{dir_name}/{package_name}")); + } + } + } + } else { + // Regular package + packages.push(dir_name.to_string()); + } + } + + // Initialize resolver + let options = ResolveOptions { + alias_fields: vec![vec!["browser".into()]], + // ESM + condition_names: vec!["node".into(), "import".into()], + ..ResolveOptions::default() + }; + let resolver = Resolver::new(options); + + packages.par_iter().for_each(|package| { + if let Err(err) = resolver.resolve(&cwd, package) { + eprintln!("{package}: {err}"); + } + }); +} From e1ef00dc17c9c2cc6d6c882dafeaeec89a543489 Mon Sep 17 00:00:00 2001 From: Boshen Date: Sun, 16 Nov 2025 12:37:55 +0000 Subject: [PATCH 07/17] perf: use IdentityHasher for visited set to avoid double hashing (#837) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Replace `FxHashSet` with `HashSet>` for the visited set in canonicalization - Avoids double hashing since the stored values are already hash values (`u64`) - Consistent with the existing usage of `IdentityHasher` for `HashSet` in the same file ## Test plan - ✅ All existing tests pass (`cargo test --lib`) - ✅ No clippy warnings (`cargo clippy --all-targets -- --deny warnings`) - ✅ Code compiles successfully 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- src/cache/cache_impl.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cache/cache_impl.rs b/src/cache/cache_impl.rs index 4c5784ca..46b2a50b 100644 --- a/src/cache/cache_impl.rs +++ b/src/cache/cache_impl.rs @@ -230,7 +230,8 @@ impl Cache { // The Result is stored inside the OnceLock to cache both success and failure cases. let result = path.canonicalized.get_or_init(|| { // Each canonicalization chain gets its own visited set for circular symlink detection - let mut visited = StdHashSet::new(); + let mut visited = + StdHashSet::with_hasher(BuildHasherDefault::::default()); self.canonicalize_with_visited(path, &mut visited).map(|cp| Arc::downgrade(&cp.0)) }); @@ -252,7 +253,7 @@ impl Cache { fn canonicalize_with_visited( &self, path: &CachedPath, - visited: &mut StdHashSet, + visited: &mut StdHashSet>, ) -> Result { // Check for circular symlink by tracking visited paths in the current canonicalization chain if !visited.insert(path.hash) { From d8ecae8dcf35629362e456e62731ac815166ed1d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 16 Nov 2025 16:48:43 +0000 Subject: [PATCH 08/17] chore(deps): update github-actions (#841) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [CodSpeedHQ/action](https://redirect.github.com/CodSpeedHQ/action) | action | patch | `v4.3.3` -> `v4.3.4` | | [github/codeql-action](https://redirect.github.com/github/codeql-action) | action | patch | `v4.31.2` -> `v4.31.3` | | [taiki-e/install-action](https://redirect.github.com/taiki-e/install-action) | action | patch | `v2.62.49` -> `v2.62.51` | --- ### Release Notes
CodSpeedHQ/action (CodSpeedHQ/action) ### [`v4.3.4`](https://redirect.github.com/CodSpeedHQ/action/releases/tag/v4.3.4) [Compare Source](https://redirect.github.com/CodSpeedHQ/action/compare/v4.3.3...v4.3.4) #### Release Notes ##### 🚀 Features - Make `get_commit_hash` different based on the provider by [@​GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange) in [#​151](https://redirect.github.com/CodSpeedHQ/runner/pull/151) ##### 🐛 Bug Fixes - Use GITHUB\_WORKSPACE env var when computing root path by [@​GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange) - Ensure perf also fails when the command fails by [@​not-matthias](https://redirect.github.com/not-matthias) in [#​150](https://redirect.github.com/CodSpeedHQ/runner/pull/150) - Ensure working directory is used when running the cmd by [@​not-matthias](https://redirect.github.com/not-matthias) - Use debug! instead of println for debug data by [@​art049](https://redirect.github.com/art049) ##### ⚙️ Internals - chore: bump runner version to 4.3.4 by [@​github-actions](https://redirect.github.com/github-actions)\[bot] in [#​154](https://redirect.github.com/CodSpeedHQ/action/pull/154) #### Install codspeed-runner 4.3.4 ##### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/CodSpeedHQ/runner/releases/download/v4.3.4/codspeed-runner-installer.sh | sh ``` #### Download codspeed-runner 4.3.4 | File | Platform | Checksum | | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | [codspeed-runner-aarch64-unknown-linux-musl.tar.gz](https://redirect.github.com/CodSpeedHQ/runner/releases/download/v4.3.4/codspeed-runner-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://redirect.github.com/CodSpeedHQ/runner/releases/download/v4.3.4/codspeed-runner-aarch64-unknown-linux-musl.tar.gz.sha256) | | [codspeed-runner-x86\_64-unknown-linux-musl.tar.gz](https://redirect.github.com/CodSpeedHQ/runner/releases/download/v4.3.4/codspeed-runner-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://redirect.github.com/CodSpeedHQ/runner/releases/download/v4.3.4/codspeed-runner-x86_64-unknown-linux-musl.tar.gz.sha256) | **Full Runner Changelog**: **Full Changelog**:
github/codeql-action (github/codeql-action) ### [`v4.31.3`](https://redirect.github.com/github/codeql-action/releases/tag/v4.31.3) [Compare Source](https://redirect.github.com/github/codeql-action/compare/v4.31.2...v4.31.3) ##### CodeQL Action Changelog See the [releases page](https://redirect.github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. ##### 4.31.3 - 13 Nov 2025 - CodeQL Action v3 will be deprecated in December 2026. The Action now logs a warning for customers who are running v3 but could be running v4. For more information, see [Upcoming deprecation of CodeQL Action v3](https://github.blog/changelog/2025-10-28-upcoming-deprecation-of-codeql-action-v3/). - Update default CodeQL bundle version to 2.23.5. [#​3288](https://redirect.github.com/github/codeql-action/pull/3288) See the full [CHANGELOG.md](https://redirect.github.com/github/codeql-action/blob/v4.31.3/CHANGELOG.md) for more information.
taiki-e/install-action (taiki-e/install-action) ### [`v2.62.51`](https://redirect.github.com/taiki-e/install-action/blob/HEAD/CHANGELOG.md#100---2021-12-30) [Compare Source](https://redirect.github.com/taiki-e/install-action/compare/v2.62.50...v2.62.51) Initial release [Unreleased]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.51...HEAD [2.62.51]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.50...v2.62.51 [2.62.50]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.49...v2.62.50 [2.62.49]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.48...v2.62.49 [2.62.48]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.47...v2.62.48 [2.62.47]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.46...v2.62.47 [2.62.46]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.45...v2.62.46 [2.62.45]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.44...v2.62.45 [2.62.44]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.43...v2.62.44 [2.62.43]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.42...v2.62.43 [2.62.42]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.41...v2.62.42 [2.62.41]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.40...v2.62.41 [2.62.40]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.39...v2.62.40 [2.62.39]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.38...v2.62.39 [2.62.38]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.37...v2.62.38 [2.62.37]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.36...v2.62.37 [2.62.36]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.35...v2.62.36 [2.62.35]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.34...v2.62.35 [2.62.34]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.33...v2.62.34 [2.62.33]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.32...v2.62.33 [2.62.32]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.31...v2.62.32 [2.62.31]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.30...v2.62.31 [2.62.30]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.29...v2.62.30 [2.62.29]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.28...v2.62.29 [2.62.28]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.27...v2.62.28 [2.62.27]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.26...v2.62.27 [2.62.26]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.25...v2.62.26 [2.62.25]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.24...v2.62.25 [2.62.24]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.23...v2.62.24 [2.62.23]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.22...v2.62.23 [2.62.22]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.21...v2.62.22 [2.62.21]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.20...v2.62.21 [2.62.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.19...v2.62.20 [2.62.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.18...v2.62.19 [2.62.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.17...v2.62.18 [2.62.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.16...v2.62.17 [2.62.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.15...v2.62.16 [2.62.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.14...v2.62.15 [2.62.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.13...v2.62.14 [2.62.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.12...v2.62.13 [2.62.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.11...v2.62.12 [2.62.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.10...v2.62.11 [2.62.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.9...v2.62.10 [2.62.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.8...v2.62.9 [2.62.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.7...v2.62.8 [2.62.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.6...v2.62.7 [2.62.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.5...v2.62.6 [2.62.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.4...v2.62.5 [2.62.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.3...v2.62.4 [2.62.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.2...v2.62.3 [2.62.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.1...v2.62.2 [2.62.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.62.0...v2.62.1 [2.62.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.13...v2.62.0 [2.61.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.12...v2.61.13 [2.61.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.11...v2.61.12 [2.61.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.10...v2.61.11 [2.61.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.9...v2.61.10 [2.61.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.8...v2.61.9 [2.61.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.7...v2.61.8 [2.61.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.6...v2.61.7 [2.61.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.5...v2.61.6 [2.61.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.4...v2.61.5 [2.61.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.3...v2.61.4 [2.61.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.2...v2.61.3 [2.61.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.1...v2.61.2 [2.61.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.61.0...v2.61.1 [2.61.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.60.0...v2.61.0 [2.60.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.59.1...v2.60.0 [2.59.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.59.0...v2.59.1 [2.59.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.33...v2.59.0 [2.58.33]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.32...v2.58.33 [2.58.32]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.31...v2.58.32 [2.58.31]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.30...v2.58.31 [2.58.30]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.29...v2.58.30 [2.58.29]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.28...v2.58.29 [2.58.28]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.27...v2.58.28 [2.58.27]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.26...v2.58.27 [2.58.26]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.25...v2.58.26 [2.58.25]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.24...v2.58.25 [2.58.24]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.23...v2.58.24 [2.58.23]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.22...v2.58.23 [2.58.22]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.21...v2.58.22 [2.58.21]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.20...v2.58.21 [2.58.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.19...v2.58.20 [2.58.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.18...v2.58.19 [2.58.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.17...v2.58.18 [2.58.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.16...v2.58.17 [2.58.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.15...v2.58.16 [2.58.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.14...v2.58.15 [2.58.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.13...v2.58.14 [2.58.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.12...v2.58.13 [2.58.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.11...v2.58.12 [2.58.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.10...v2.58.11 [2.58.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.9...v2.58.10 [2.58.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.8...v2.58.9 [2.58.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.7...v2.58.8 [2.58.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.6...v2.58.7 [2.58.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.5...v2.58.6 [2.58.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.4...v2.58.5 [2.58.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.3...v2.58.4 [2.58.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.2...v2.58.3 [2.58.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.1...v2.58.2 [2.58.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.58.0...v2.58.1 [2.58.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.57.8...v2.58.0 [2.57.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.57.7...v2.57.8 [2.57.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.57.6...v2.57.7 [2.57.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.57.5...v2.57.6 [2.57.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.57.4...v2.57.5 [2.57.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.57.3...v2.57.4 [2.57.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.57.2...v2.57.3 [2.57.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.57.1...v2.57.2 [2.57.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.57.0...v2.57.1 [2.57.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.24...v2.57.0 [2.56.24]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.23...v2.56.24 [2.56.23]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.22...v2.56.23 [2.56.22]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.21...v2.56.22 [2.56.21]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.20...v2.56.21 [2.56.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.19...v2.56.20 [2.56.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.18...v2.56.19 [2.56.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.17...v2.56.18 [2.56.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.16...v2.56.17 [2.56.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.15...v2.56.16 [2.56.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.14...v2.56.15 [2.56.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.13...v2.56.14 [2.56.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.12...v2.56.13 [2.56.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.11...v2.56.12 [2.56.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.10...v2.56.11 [2.56.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.9...v2.56.10 [2.56.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.8...v2.56.9 [2.56.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.7...v2.56.8 [2.56.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.6...v2.56.7 [2.56.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.5...v2.56.6 [2.56.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.4...v2.56.5 [2.56.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.3...v2.56.4 [2.56.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.2...v2.56.3 [2.56.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.1...v2.56.2 [2.56.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.56.0...v2.56.1 [2.56.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.55.4...v2.56.0 [2.55.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.55.3...v2.55.4 [2.55.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.55.2...v2.55.3 [2.55.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.55.1...v2.55.2 [2.55.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.55.0...v2.55.1 [2.55.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.54.3...v2.55.0 [2.54.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.54.2...v2.54.3 [2.54.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.54.1...v2.54.2 [2.54.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.54.0...v2.54.1 [2.54.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.53.2...v2.54.0 [2.53.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.53.1...v2.53.2 [2.53.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.53.0...v2.53.1 [2.53.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.52.8...v2.53.0 [2.52.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.52.7...v2.52.8 [2.52.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.52.6...v2.52.7 [2.52.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.52.5...v2.52.6 [2.52.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.52.4...v2.52.5 [2.52.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.52.3...v2.52.4 [2.52.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.52.2...v2.52.3 [2.52.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.52.1...v2.52.2 [2.52.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.52.0...v2.52.1 [2.52.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.51.3...v2.52.0 [2.51.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.51.2...v2.51.3 [2.51.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.51.1...v2.51.2 [2.51.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.51.0...v2.51.1 [2.51.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.10...v2.51.0 [2.50.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.9...v2.50.10 [2.50.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.8...v2.50.9 [2.50.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.7...v2.50.8 [2.50.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.6...v2.50.7 [2.50.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.5...v2.50.6 [2.50.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.4...v2.50.5 [2.50.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.3...v2.50.4 [2.50.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.2...v2.50.3 [2.50.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.1...v2.50.2 [2.50.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.50.0...v2.50.1 [2.50.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.50...v2.50.0 [2.49.50]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.49...v2.49.50 [2.49.49]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.48...v2.49.49 [2.49.48]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.47...v2.49.48 [2.49.47]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.46...v2.49.47 [2.49.46]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.45...v2.49.46 [2.49.45]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.44...v2.49.45 [2.49.44]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.43...v2.49.44 [2.49.43]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.42...v2.49.43 [2.49.42]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.41...v2.49.42 [2.49.41]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.40...v2.49.41 [2.49.40]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.39...v2.49.40 [2.49.39]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.38...v2.49.39 [2.49.38]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.37...v2.49.38 [2.49.37]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.36...v2.49.37 [2.49.36]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.35...v2.49.36 [2.49.35]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.34...v2.49.35 [2.49.34]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.33...v2.49.34 [2.49.33]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.32...v2.49.33 [2.49.32]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.31...v2.49.32 [2.49.31]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.30...v2.49.31 [2.49.30]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.29...v2.49.30 [2.49.29]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.28...v2.49.29 [2.49.28]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.27...v2.49.28 [2.49.27]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.26...v2.49.27 [2.49.26]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.25...v2.49.26 [2.49.25]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.24...v2.49.25 [2.49.24]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.23...v2.49.24 [2.49.23]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.22...v2.49.23 [2.49.22]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.21...v2.49.22 [2.49.21]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.20...v2.49.21 [2.49.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.19...v2.49.20 [2.49.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.18...v2.49.19 [2.49.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.17...v2.49.18 [2.49.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.16...v2.49.17 [2.49.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.15...v2.49.16 [2.49.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.14...v2.49.15 [2.49.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.13...v2.49.14 [2.49.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.12...v2.49.13 [2.49.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.11...v2.49.12 [2.49.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.10...v2.49.11 [2.49.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.9...v2.49.10 [2.49.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.8...v2.49.9 [2.49.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.7...v2.49.8 [2.49.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.6...v2.49.7 [2.49.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.5...v2.49.6 [2.49.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.4...v2.49.5 [2.49.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.3...v2.49.4 [2.49.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.2...v2.49.3 [2.49.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.1...v2.49.2 [2.49.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.49.0...v2.49.1 [2.49.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.22...v2.49.0 [2.48.22]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.21...v2.48.22 [2.48.21]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.20...v2.48.21 [2.48.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.19...v2.48.20 [2.48.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.18...v2.48.19 [2.48.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.17...v2.48.18 [2.48.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.16...v2.48.17 [2.48.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.15...v2.48.16 [2.48.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.14...v2.48.15 [2.48.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.13...v2.48.14 [2.48.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.12...v2.48.13 [2.48.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.11...v2.48.12 [2.48.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.10...v2.48.11 [2.48.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.9...v2.48.10 [2.48.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.8...v2.48.9 [2.48.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.7...v2.48.8 [2.48.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.6...v2.48.7 [2.48.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.5...v2.48.6 [2.48.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.4...v2.48.5 [2.48.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.3...v2.48.4 [2.48.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.2...v2.48.3 [2.48.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.1...v2.48.2 [2.48.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.48.0...v2.48.1 [2.48.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.32...v2.48.0 [2.47.32]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.31...v2.47.32 [2.47.31]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.30...v2.47.31 [2.47.30]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.29...v2.47.30 [2.47.29]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.28...v2.47.29 [2.47.28]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.27...v2.47.28 [2.47.27]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.26...v2.47.27 [2.47.26]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.25...v2.47.26 [2.47.25]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.24...v2.47.25 [2.47.24]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.23...v2.47.24 [2.47.23]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.22...v2.47.23 [2.47.22]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.21...v2.47.22 [2.47.21]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.20...v2.47.21 [2.47.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.19...v2.47.20 [2.47.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.18...v2.47.19 [2.47.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.17...v2.47.18 [2.47.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.16...v2.47.17 [2.47.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.15...v2.47.16 [2.47.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.14...v2.47.15 [2.47.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.13...v2.47.14 [2.47.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.12...v2.47.13 [2.47.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.11...v2.47.12 [2.47.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.10...v2.47.11 [2.47.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.9...v2.47.10 [2.47.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.8...v2.47.9 [2.47.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.7...v2.47.8 [2.47.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.6...v2.47.7 [2.47.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.5...v2.47.6 [2.47.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.4...v2.47.5 [2.47.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.3...v2.47.4 [2.47.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.2...v2.47.3 [2.47.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.1...v2.47.2 [2.47.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.47.0...v2.47.1 [2.47.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.20...v2.47.0 [2.46.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.19...v2.46.20 [2.46.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.18...v2.46.19 [2.46.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.17...v2.46.18 [2.46.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.16...v2.46.17 [2.46.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.15...v2.46.16 [2.46.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.14...v2.46.15 [2.46.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.13...v2.46.14 [2.46.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.12...v2.46.13 [2.46.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.11...v2.46.12 [2.46.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.10...v2.46.11 [2.46.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.9...v2.46.10 [2.46.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.8...v2.46.9 [2.46.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.7...v2.46.8 [2.46.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.6...v2.46.7 [2.46.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.5...v2.46.6 [2.46.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.4...v2.46.5 [2.46.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.3...v2.46.4 [2.46.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.2...v2.46.3 [2.46.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.1...v2.46.2 [2.46.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.46.0...v2.46.1 [2.46.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.15...v2.46.0 [2.45.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.14...v2.45.15 [2.45.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.13...v2.45.14 [2.45.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.12...v2.45.13 [2.45.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.11...v2.45.12 [2.45.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.10...v2.45.11 [2.45.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.9...v2.45.10 [2.45.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.8...v2.45.9 [2.45.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.7...v2.45.8 [2.45.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.6...v2.45.7 [2.45.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.5...v2.45.6 [2.45.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.4...v2.45.5 [2.45.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.3...v2.45.4 [2.45.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.2...v2.45.3 [2.45.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.1...v2.45.2 [2.45.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.45.0...v2.45.1 [2.45.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.72...v2.45.0 [2.44.72]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.71...v2.44.72 [2.44.71]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.70...v2.44.71 [2.44.70]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.69...v2.44.70 [2.44.69]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.68...v2.44.69 [2.44.68]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.67...v2.44.68 [2.44.67]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.66...v2.44.67 [2.44.66]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.65...v2.44.66 [2.44.65]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.64...v2.44.65 [2.44.64]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.63...v2.44.64 [2.44.63]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.62...v2.44.63 [2.44.62]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.61...v2.44.62 [2.44.61]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.60...v2.44.61 [2.44.60]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.59...v2.44.60 [2.44.59]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.58...v2.44.59 [2.44.58]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.57...v2.44.58 [2.44.57]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.56...v2.44.57 [2.44.56]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.55...v2.44.56 [2.44.55]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.54...v2.44.55 [2.44.54]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.53...v2.44.54 [2.44.53]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.52...v2.44.53 [2.44.52]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.51...v2.44.52 [2.44.51]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.50...v2.44.51 [2.44.50]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.49...v2.44.50 [2.44.49]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.48...v2.44.49 [2.44.48]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.47...v2.44.48 [2.44.47]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.46...v2.44.47 [2.44.46]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.45...v2.44.46 [2.44.45]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.44...v2.44.45 [2.44.44]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.43...v2.44.44 [2.44.43]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.42...v2.44.43 [2.44.42]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.41...v2.44.42 [2.44.41]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.40...v2.44.41 [2.44.40]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.39...v2.44.40 [2.44.39]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.38...v2.44.39 [2.44.38]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.37...v2.44.38 [2.44.37]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.36...v2.44.37 [2.44.36]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.35...v2.44.36 [2.44.35]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.34...v2.44.35 [2.44.34]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.33...v2.44.34 [2.44.33]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.32...v2.44.33 [2.44.32]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.31...v2.44.32 [2.44.31]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.30...v2.44.31 [2.44.30]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.29...v2.44.30 [2.44.29]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.28...v2.44.29 [2.44.28]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.27...v2.44.28 [2.44.27]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.26...v2.44.27 [2.44.26]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.25...v2.44.26 [2.44.25]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.24...v2.44.25 [2.44.24]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.23...v2.44.24 [2.44.23]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.22...v2.44.23 [2.44.22]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.21...v2.44.22 [2.44.21]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.20...v2.44.21 [2.44.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.19...v2.44.20 [2.44.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.18...v2.44.19 [2.44.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.17...v2.44.18 [2.44.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.16...v2.44.17 [2.44.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.15...v2.44.16 [2.44.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.14...v2.44.15 [2.44.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.13...v2.44.14 [2.44.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.12...v2.44.13 [2.44.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.11...v2.44.12 [2.44.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.10...v2.44.11 [2.44.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.9...v2.44.10 [2.44.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.8...v2.44.9 [2.44.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.7...v2.44.8 [2.44.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.6...v2.44.7 [2.44.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.5...v2.44.6 [2.44.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.4...v2.44.5 [2.44.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.3...v2.44.4 [2.44.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.2...v2.44.3 [2.44.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.1...v2.44.2 [2.44.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.44.0...v2.44.1 [2.44.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.43.7...v2.44.0 [2.43.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.43.6...v2.43.7 [2.43.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.43.5...v2.43.6 [2.43.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.43.4...v2.43.5 [2.43.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.43.3...v2.43.4 [2.43.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.43.2...v2.43.3 [2.43.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.43.1...v2.43.2 [2.43.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.43.0...v2.43.1 [2.43.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.42...v2.43.0 [2.42.42]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.41...v2.42.42 [2.42.41]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.40...v2.42.41 [2.42.40]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.39...v2.42.40 [2.42.39]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.38...v2.42.39 [2.42.38]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.37...v2.42.38 [2.42.37]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.36...v2.42.37 [2.42.36]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.35...v2.42.36 [2.42.35]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.34...v2.42.35 [2.42.34]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.33...v2.42.34 [2.42.33]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.32...v2.42.33 [2.42.32]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.31...v2.42.32 [2.42.31]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.30...v2.42.31 [2.42.30]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.29...v2.42.30 [2.42.29]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.28...v2.42.29 [2.42.28]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.27...v2.42.28 [2.42.27]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.26...v2.42.27 [2.42.26]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.25...v2.42.26 [2.42.25]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.24...v2.42.25 [2.42.24]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.23...v2.42.24 [2.42.23]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.22...v2.42.23 [2.42.22]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.21...v2.42.22 [2.42.21]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.20...v2.42.21 [2.42.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.19...v2.42.20 [2.42.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.18...v2.42.19 [2.42.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.17...v2.42.18 [2.42.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.16...v2.42.17 [2.42.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.15...v2.42.16 [2.42.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.14...v2.42.15 [2.42.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.13...v2.42.14 [2.42.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.12...v2.42.13 [2.42.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.11...v2.42.12 [2.42.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.10...v2.42.11 [2.42.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.9...v2.42.10 [2.42.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.8...v2.42.9 [2.42.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.7...v2.42.8 [2.42.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.6...v2.42.7 [2.42.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.5...v2.42.6 [2.42.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.4...v2.42.5 [2.42.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.3...v2.42.4 [2.42.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.2...v2.42.3 [2.42.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.1...v2.42.2 [2.42.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.42.0...v2.42.1 [2.42.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.18...v2.42.0 [2.41.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.17...v2.41.18 [2.41.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.16...v2.41.17 [2.41.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.15...v2.41.16 [2.41.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.14...v2.41.15 [2.41.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.13...v2.41.14 [2.41.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.12...v2.41.13 [2.41.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.11...v2.41.12 [2.41.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.10...v2.41.11 [2.41.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.9...v2.41.10 [2.41.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.8...v2.41.9 [2.41.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.7...v2.41.8 [2.41.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.6...v2.41.7 [2.41.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.5...v2.41.6 [2.41.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.4...v2.41.5 [2.41.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.3...v2.41.4 [2.41.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.2...v2.41.3 [2.41.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.1...v2.41.2 [2.41.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.41.0...v2.41.1 [2.41.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.40.2...v2.41.0 [2.40.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.40.1...v2.40.2 [2.40.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.40.0...v2.40.1 [2.40.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.39.2...v2.40.0 [2.39.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.39.1...v2.39.2 [2.39.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.39.0...v2.39.1 [2.39.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.38.7...v2.39.0 [2.38.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.38.6...v2.38.7 [2.38.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.38.5...v2.38.6 [2.38.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.38.4...v2.38.5 [2.38.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.38.3...v2.38.4 [2.38.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.38.2...v2.38.3 [2.38.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.38.1...v2.38.2 [2.38.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.38.0...v2.38.1 [2.38.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.37.0...v2.38.0 [2.37.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.36.0...v2.37.0 [2.36.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.35.0...v2.36.0 [2.35.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.34.3...v2.35.0 [2.34.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.34.2...v2.34.3 [2.34.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.34.1...v2.34.2 [2.34.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.34.0...v2.34.1 [2.34.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.36...v2.34.0 [2.33.36]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.35...v2.33.36 [2.33.35]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.34...v2.33.35 [2.33.34]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.33...v2.33.34 [2.33.33]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.32...v2.33.33 [2.33.32]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.31...v2.33.32 [2.33.31]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.30...v2.33.31 [2.33.30]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.29...v2.33.30 [2.33.29]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.28...v2.33.29 [2.33.28]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.27...v2.33.28 [2.33.27]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.26...v2.33.27 [2.33.26]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.25...v2.33.26 [2.33.25]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.24...v2.33.25 [2.33.24]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.23...v2.33.24 [2.33.23]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.22...v2.33.23 [2.33.22]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.21...v2.33.22 [2.33.21]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.20...v2.33.21 [2.33.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.19...v2.33.20 [2.33.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.18...v2.33.19 [2.33.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.17...v2.33.18 [2.33.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.16...v2.33.17 [2.33.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.15...v2.33.16 [2.33.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.14...v2.33.15 [2.33.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.13...v2.33.14 [2.33.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.12...v2.33.13 [2.33.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.11...v2.33.12 [2.33.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.10...v2.33.11 [2.33.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.9...v2.33.10 [2.33.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.8...v2.33.9 [2.33.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.7...v2.33.8 [2.33.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.6...v2.33.7 [2.33.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.5...v2.33.6 [2.33.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.4...v2.33.5 [2.33.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.3...v2.33.4 [2.33.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.2...v2.33.3 [2.33.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.1...v2.33.2 [2.33.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.33.0...v2.33.1 [2.33.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.20...v2.33.0 [2.32.20]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.19...v2.32.20 [2.32.19]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.18...v2.32.19 [2.32.18]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.17...v2.32.18 [2.32.17]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.16...v2.32.17 [2.32.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.15...v2.32.16 [2.32.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.14...v2.32.15 [2.32.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.13...v2.32.14 [2.32.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.12...v2.32.13 [2.32.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.11...v2.32.12 [2.32.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.10...v2.32.11 [2.32.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.9...v2.32.10 [2.32.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.8...v2.32.9 [2.32.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.7...v2.32.8 [2.32.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.6...v2.32.7 [2.32.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.5...v2.32.6 [2.32.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.4...v2.32.5 [2.32.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.3...v2.32.4 [2.32.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.2...v2.32.3 [2.32.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.1...v2.32.2 [2.32.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.32.0...v2.32.1 [2.32.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.31.3...v2.32.0 [2.31.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.31.2...v2.31.3 [2.31.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.31.1...v2.31.2 [2.31.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.31.0...v2.31.1 [2.31.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.30.0...v2.31.0 [2.30.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.29.8...v2.30.0 [2.29.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.29.7...v2.29.8 [2.29.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.29.6...v2.29.7 [2.29.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.29.5...v2.29.6 [2.29.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.29.4...v2.29.5 [2.29.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.29.3...v2.29.4 [2.29.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.29.2...v2.29.3 [2.29.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.29.1...v2.29.2 [2.29.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.29.0...v2.29.1 [2.29.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.16...v2.29.0 [2.28.16]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.15...v2.28.16 [2.28.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.14...v2.28.15 [2.28.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.13...v2.28.14 [2.28.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.12...v2.28.13 [2.28.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.11...v2.28.12 [2.28.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.10...v2.28.11 [2.28.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.9...v2.28.10 [2.28.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.8...v2.28.9 [2.28.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.7...v2.28.8 [2.28.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.6...v2.28.7 [2.28.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.5...v2.28.6 [2.28.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.4...v2.28.5 [2.28.4]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.3...v2.28.4 [2.28.3]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.2...v2.28.3 [2.28.2]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.1...v2.28.2 [2.28.1]: https://redirect.github.com/taiki-e/install-action/compare/v2.28.0...v2.28.1 [2.28.0]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.15...v2.28.0 [2.27.15]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.14...v2.27.15 [2.27.14]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.13...v2.27.14 [2.27.13]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.12...v2.27.13 [2.27.12]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.11...v2.27.12 [2.27.11]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.10...v2.27.11 [2.27.10]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.9...v2.27.10 [2.27.9]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.8...v2.27.9 [2.27.8]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.7...v2.27.8 [2.27.7]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.6...v2.27.7 [2.27.6]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.5...v2.27.6 [2.27.5]: https://redirect.github.com/taiki-e/install-action/compare/v2.27.4...v2.27.5 [2.27.4]: https://redirect.github.com/taiki-e/inst
--- ### Configuration 📅 **Schedule**: Branch creation - "before 10am on monday" in timezone Asia/Shanghai, Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] 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-resolver). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/benchmark.yml | 2 +- .github/workflows/zizmor.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index fd8a0c6e..ea25709f 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -35,7 +35,7 @@ jobs: env: RUSTFLAGS: "-C debuginfo=1 -C strip=none" - - uses: CodSpeedHQ/action@bb005fe1c1eea036d3894f02c049cb6b154a1c27 # v4.3.3 + - uses: CodSpeedHQ/action@6a8e2b874c338bf81cc5e8be715ada75908d3871 # v4.3.4 timeout-minutes: 30 with: run: cargo codspeed run diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 335cda0e..aec34df0 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -29,7 +29,7 @@ jobs: steps: - uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1 - - uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2.62.49 + - uses: taiki-e/install-action@0be4756f42223b67aa4b7df5effad59010cbf4b9 # v2.62.51 with: tool: zizmor @@ -39,7 +39,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2 + uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3 with: sarif_file: results.sarif category: zizmor From 4528a3ff9a8a01b104fef0e2d719d7f1f61d3c4b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 16 Nov 2025 16:49:45 +0000 Subject: [PATCH 09/17] chore(deps): update npm packages (#842) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`24.10.0` -> `24.10.1`](https://renovatebot.com/diffs/npm/@types%2fnode/24.10.0/24.10.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/24.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/24.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/24.10.0/24.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/24.10.0/24.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [pnpm](https://pnpm.io) ([source](https://redirect.github.com/pnpm/pnpm/tree/HEAD/pnpm)) | [`10.20.0` -> `10.22.0`](https://renovatebot.com/diffs/npm/pnpm/10.20.0/10.22.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/10.22.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/pnpm/10.22.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/pnpm/10.20.0/10.22.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/10.20.0/10.22.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
pnpm/pnpm (pnpm) ### [`v10.22.0`](https://redirect.github.com/pnpm/pnpm/compare/v10.21.0...v10.22.0) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v10.21.0...v10.22.0) ### [`v10.21.0`](https://redirect.github.com/pnpm/pnpm/compare/v10.20.0...v10.21.0) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v10.20.0...v10.21.0)
--- ### Configuration 📅 **Schedule**: Branch creation - "before 10am on monday" in timezone Asia/Shanghai, Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] 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-resolver). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- pnpm-lock.yaml | 156 ++++++++++++++++++++++++------------------------- 2 files changed, 79 insertions(+), 79 deletions(-) diff --git a/package.json b/package.json index c87b876a..e3e36cc8 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "11.13.2", "license": "MIT", "description": "Oxc Resolver Node API", - "packageManager": "pnpm@10.20.0", + "packageManager": "pnpm@10.22.0", "homepage": "https://oxc.rs", "repository": { "type": "git", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c148eabc..de302896 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,13 +10,13 @@ importers: devDependencies: '@napi-rs/cli': specifier: ^3.3.1 - version: 3.4.1(@emnapi/runtime@1.7.0)(@types/node@24.10.0) + version: 3.4.1(@emnapi/runtime@1.7.0)(@types/node@24.10.1) '@napi-rs/wasm-runtime': specifier: ^1.0.7 version: 1.0.7 '@types/node': specifier: ^24.9.1 - version: 24.10.0 + version: 24.10.1 emnapi: specifier: ^1.6.0 version: 1.7.0 @@ -25,7 +25,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.0.0 - version: 4.0.8(@types/node@24.10.0) + version: 4.0.8(@types/node@24.10.1) fixtures/pnpm: devDependencies: @@ -905,8 +905,8 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/node@24.10.0': - resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==} + '@types/node@24.10.1': + resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} '@types/stylis@4.2.5': resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==} @@ -1541,134 +1541,134 @@ snapshots: '@inquirer/ansi@1.0.2': {} - '@inquirer/checkbox@4.3.1(@types/node@24.10.0)': + '@inquirer/checkbox@4.3.1(@types/node@24.10.1)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.1(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/type': 3.0.10(@types/node@24.10.1) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/confirm@5.1.20(@types/node@24.10.0)': + '@inquirer/confirm@5.1.20(@types/node@24.10.1)': dependencies: - '@inquirer/core': 10.3.1(@types/node@24.10.0) - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.1) optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/core@10.3.1(@types/node@24.10.0)': + '@inquirer/core@10.3.1(@types/node@24.10.1)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/type': 3.0.10(@types/node@24.10.1) cli-width: 4.1.0 mute-stream: 3.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/editor@4.2.22(@types/node@24.10.0)': + '@inquirer/editor@4.2.22(@types/node@24.10.1)': dependencies: - '@inquirer/core': 10.3.1(@types/node@24.10.0) - '@inquirer/external-editor': 1.0.3(@types/node@24.10.0) - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) + '@inquirer/external-editor': 1.0.3(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.1) optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/expand@4.0.22(@types/node@24.10.0)': + '@inquirer/expand@4.0.22(@types/node@24.10.1)': dependencies: - '@inquirer/core': 10.3.1(@types/node@24.10.0) - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.1) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/external-editor@1.0.3(@types/node@24.10.0)': + '@inquirer/external-editor@1.0.3(@types/node@24.10.1)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.0 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 '@inquirer/figures@1.0.15': {} - '@inquirer/input@4.3.0(@types/node@24.10.0)': + '@inquirer/input@4.3.0(@types/node@24.10.1)': dependencies: - '@inquirer/core': 10.3.1(@types/node@24.10.0) - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.1) optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/number@3.0.22(@types/node@24.10.0)': + '@inquirer/number@3.0.22(@types/node@24.10.1)': dependencies: - '@inquirer/core': 10.3.1(@types/node@24.10.0) - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.1) optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/password@4.0.22(@types/node@24.10.0)': + '@inquirer/password@4.0.22(@types/node@24.10.1)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.1(@types/node@24.10.0) - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.1) optionalDependencies: - '@types/node': 24.10.0 - - '@inquirer/prompts@7.10.0(@types/node@24.10.0)': - dependencies: - '@inquirer/checkbox': 4.3.1(@types/node@24.10.0) - '@inquirer/confirm': 5.1.20(@types/node@24.10.0) - '@inquirer/editor': 4.2.22(@types/node@24.10.0) - '@inquirer/expand': 4.0.22(@types/node@24.10.0) - '@inquirer/input': 4.3.0(@types/node@24.10.0) - '@inquirer/number': 3.0.22(@types/node@24.10.0) - '@inquirer/password': 4.0.22(@types/node@24.10.0) - '@inquirer/rawlist': 4.1.10(@types/node@24.10.0) - '@inquirer/search': 3.2.1(@types/node@24.10.0) - '@inquirer/select': 4.4.1(@types/node@24.10.0) + '@types/node': 24.10.1 + + '@inquirer/prompts@7.10.0(@types/node@24.10.1)': + dependencies: + '@inquirer/checkbox': 4.3.1(@types/node@24.10.1) + '@inquirer/confirm': 5.1.20(@types/node@24.10.1) + '@inquirer/editor': 4.2.22(@types/node@24.10.1) + '@inquirer/expand': 4.0.22(@types/node@24.10.1) + '@inquirer/input': 4.3.0(@types/node@24.10.1) + '@inquirer/number': 3.0.22(@types/node@24.10.1) + '@inquirer/password': 4.0.22(@types/node@24.10.1) + '@inquirer/rawlist': 4.1.10(@types/node@24.10.1) + '@inquirer/search': 3.2.1(@types/node@24.10.1) + '@inquirer/select': 4.4.1(@types/node@24.10.1) optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/rawlist@4.1.10(@types/node@24.10.0)': + '@inquirer/rawlist@4.1.10(@types/node@24.10.1)': dependencies: - '@inquirer/core': 10.3.1(@types/node@24.10.0) - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.1) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/search@3.2.1(@types/node@24.10.0)': + '@inquirer/search@3.2.1(@types/node@24.10.1)': dependencies: - '@inquirer/core': 10.3.1(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/type': 3.0.10(@types/node@24.10.1) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/select@4.4.1(@types/node@24.10.0)': + '@inquirer/select@4.4.1(@types/node@24.10.1)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.1(@types/node@24.10.0) + '@inquirer/core': 10.3.1(@types/node@24.10.1) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.10.0) + '@inquirer/type': 3.0.10(@types/node@24.10.1) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 - '@inquirer/type@3.0.10(@types/node@24.10.0)': + '@inquirer/type@3.0.10(@types/node@24.10.1)': optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 '@jridgewell/sourcemap-codec@1.5.5': {} - '@napi-rs/cli@3.4.1(@emnapi/runtime@1.7.0)(@types/node@24.10.0)': + '@napi-rs/cli@3.4.1(@emnapi/runtime@1.7.0)(@types/node@24.10.1)': dependencies: - '@inquirer/prompts': 7.10.0(@types/node@24.10.0) + '@inquirer/prompts': 7.10.0(@types/node@24.10.1) '@napi-rs/cross-toolchain': 1.0.3 '@napi-rs/wasm-tools': 1.0.1 '@octokit/rest': 22.0.1 @@ -2055,7 +2055,7 @@ snapshots: '@types/estree@1.0.8': {} - '@types/node@24.10.0': + '@types/node@24.10.1': dependencies: undici-types: 7.16.0 @@ -2070,13 +2070,13 @@ snapshots: chai: 6.2.0 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.8(vite@7.2.2(@types/node@24.10.0))': + '@vitest/mocker@4.0.8(vite@7.2.2(@types/node@24.10.1))': dependencies: '@vitest/spy': 4.0.8 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.2.2(@types/node@24.10.0) + vite: 7.2.2(@types/node@24.10.1) '@vitest/pretty-format@4.0.8': dependencies: @@ -2489,7 +2489,7 @@ snapshots: universal-user-agent@7.0.3: {} - vite@7.2.2(@types/node@24.10.0): + vite@7.2.2(@types/node@24.10.1): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -2498,13 +2498,13 @@ snapshots: rollup: 4.53.1 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 fsevents: 2.3.3 - vitest@4.0.8(@types/node@24.10.0): + vitest@4.0.8(@types/node@24.10.1): dependencies: '@vitest/expect': 4.0.8 - '@vitest/mocker': 4.0.8(vite@7.2.2(@types/node@24.10.0)) + '@vitest/mocker': 4.0.8(vite@7.2.2(@types/node@24.10.1)) '@vitest/pretty-format': 4.0.8 '@vitest/runner': 4.0.8 '@vitest/snapshot': 4.0.8 @@ -2521,10 +2521,10 @@ snapshots: tinyexec: 0.3.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.2.2(@types/node@24.10.0) + vite: 7.2.2(@types/node@24.10.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.1 transitivePeerDependencies: - jiti - less From ff6e393e060685cd8f02bf6de3053c9c955ac17d Mon Sep 17 00:00:00 2001 From: Boshen Date: Mon, 17 Nov 2025 04:09:07 +0000 Subject: [PATCH 10/17] perf: cache canonicalization results at every recursion level (#843) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Broke in https://github.com/oxc-project/oxc-resolver/pull/834 Moves path.canonicalized.get_or_init() from canonicalize_impl() into the recursive canonicalize_with_visited() function. This enables caching of parent directory canonicalization results, which are then reused when canonicalizing sibling paths. Performance impact (measured with many example on monitor-oxc): - Total filesystem syscalls: 124,071 → 39,296 (-68.3%) - symlink_metadata calls: 99,169 → 17,503 (-82.4%) - read_link calls: 6,127 → 3,018 (-50.7%) The optimization is particularly effective for: - Projects with deep node_modules structures - pnpm workspaces (heavy symlink usage) - Parallel resolution of multiple packages All existing tests pass with no behavior changes. --- src/cache/cache_impl.rs | 45 +++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/cache/cache_impl.rs b/src/cache/cache_impl.rs index 46b2a50b..b5edd8ac 100644 --- a/src/cache/cache_impl.rs +++ b/src/cache/cache_impl.rs @@ -123,6 +123,7 @@ impl Cache { .map_err(ResolveError::Json) }) .cloned(); + // https://github.com/webpack/enhanced-resolve/blob/58464fc7cb56673c9aa849e68e6300239601e615/lib/DescriptionFileUtils.js#L68-L82 match &result { Ok(Some(package_json)) => { @@ -225,27 +226,17 @@ impl Cache { /// /// pub(crate) fn canonicalize_impl(&self, path: &CachedPath) -> Result { - // Use get_or_init to allow multiple threads to safely canonicalize the same path. - // Only one thread will perform the actual canonicalization, others will wait for the result. - // The Result is stored inside the OnceLock to cache both success and failure cases. - let result = path.canonicalized.get_or_init(|| { - // Each canonicalization chain gets its own visited set for circular symlink detection - let mut visited = - StdHashSet::with_hasher(BuildHasherDefault::::default()); - self.canonicalize_with_visited(path, &mut visited).map(|cp| Arc::downgrade(&cp.0)) - }); + // Each canonicalization chain gets its own visited set for circular symlink detection + let mut visited = StdHashSet::with_hasher(BuildHasherDefault::::default()); - result.as_ref().map_err(Clone::clone).and_then(|weak| { - weak.upgrade() - .map(CachedPath) - .or_else(|| { - // Cache was cleared while canonicalizing. Fall back to direct FS canonicalize - // without caching the result to ensure we still return the resolved path. - self.fs.canonicalize(path.path()).ok().map(|canonical| self.value(&canonical)) - }) - .ok_or_else(|| { - io::Error::new(io::ErrorKind::NotFound, "Path no longer exists").into() - }) + // canonicalize_with_visited now handles caching at every recursion level + self.canonicalize_with_visited(path, &mut visited).or_else(|err| { + // Fallback: if canonicalization fails and path's cache was cleared, + // try direct FS canonicalize without caching the result + self.fs + .canonicalize(path.path()) + .map(|canonical| self.value(&canonical)) + .map_err(|_| err) }) } @@ -255,6 +246,15 @@ impl Cache { path: &CachedPath, visited: &mut StdHashSet>, ) -> Result { + // Check cache first - if this path was already canonicalized, return the cached result + if let Some(cached) = path.canonicalized.get() { + return cached.as_ref().map_err(Clone::clone).and_then(|weak| { + weak.upgrade().map(CachedPath).ok_or_else(|| { + io::Error::new(io::ErrorKind::NotFound, "Cached path no longer exists").into() + }) + }); + } + // Check for circular symlink by tracking visited paths in the current canonicalization chain if !visited.insert(path.hash) { return Err(io::Error::new(io::ErrorKind::NotFound, "Circular symlink").into()); @@ -294,6 +294,11 @@ impl Cache { }, ); + // Cache the result before removing from visited set + // This ensures parent canonicalization results are cached and reused + path.canonicalized + .get_or_init(|| res.as_ref().map(|cp| Arc::downgrade(&cp.0)).map_err(Clone::clone)); + // Remove from visited set when unwinding the recursion visited.remove(&path.hash); res From f513bbdd1485d38c6571fbf35418170be4323b7e Mon Sep 17 00:00:00 2001 From: Boshen Date: Mon, 17 Nov 2025 05:52:21 +0000 Subject: [PATCH 11/17] perf: fast path for node_modules/package (#839) In cjs, the spec states ``` LOAD_NODE_MODULES(X, START) 1. let DIRS = NODE_MODULES_PATHS(START) 2. for each DIR in DIRS: a. LOAD_PACKAGE_EXPORTS(X, DIR) b. LOAD_AS_FILE(DIR/X) c. LOAD_AS_DIRECTORY(DIR/X) ``` `2.b. LOAD_AS_FILE(DIR/X)` never occurs in modern package managers, and I do not recall any circumstance that creates a lone `node_modules/X.js` file. This reduces a package lookup from ``` node_modules/X.js node_modules/X.json node_modules/X.node node_modules/X/index.js ``` to ``` node_modules/X/ (if X failed) node_modules/X.js node_modules/X.json node_modules/X.node ``` NOTE: ESM does not have `LOAD_AS_FILE(DIR/X)` logic. --- This change was introduced from - `https://github.com/oxc-project/oxc-resolver/pull/592` - `https://github.com/unrs/unrs-resolver/pull/116` These PRs do not explain a real case for `node_modules/X.js` to accept such performance regression. --- src/lib.rs | 14 ++------------ src/tests/resolve.rs | 14 -------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1d23dd52..7f937e6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -882,19 +882,11 @@ impl ResolverGeneric { let cached_path = cached_path.normalize_with(specifier, self.cache.as_ref()); - // Perf: try the directory first for package specifiers. if self.options.resolve_to_context { return Ok(self.cache.is_dir(&cached_path, ctx).then(|| cached_path.clone())); } - // `is_file` could be false because no extensions are considered yet, - // so we need to try `load_as_file` first when `specifier` does not end with a slash which indicates a dir instead. - if !specifier.ends_with('/') - && let Some(path) = self.load_as_file(&cached_path, ctx)? - { - return Ok(Some(path)); - } - + // Perf: try LOAD_AS_DIRECTORY first. No modern package manager creates `node_modules/X.js`. if self.cache.is_dir(&cached_path, ctx) { if let Some(path) = self.load_browser_field_or_alias(&cached_path, ctx)? { return Ok(Some(path)); @@ -902,9 +894,7 @@ impl ResolverGeneric { if let Some(path) = self.load_as_directory(&cached_path, ctx)? { return Ok(Some(path)); } - } - - if let Some(path) = self.load_as_directory(&cached_path, ctx)? { + } else if let Some(path) = self.load_as_file(&cached_path, ctx)? { return Ok(Some(path)); } } diff --git a/src/tests/resolve.rs b/src/tests/resolve.rs index d6181981..5c630b71 100644 --- a/src/tests/resolve.rs +++ b/src/tests/resolve.rs @@ -124,20 +124,6 @@ fn resolve_hash_as_module() { assert_eq!(resolution, Err(ResolveError::NotFound("#a".into()))); } -#[test] -fn prefer_file_over_dir() { - let f = super::fixture_root().join("prefer-file-over-dir"); - let resolver = Resolver::default(); - let data = [ - ("one level package name", f.clone(), "bar", f.join("node_modules/bar.js")), - ("scoped level package name", f.clone(), "@foo/bar", f.join("node_modules/@foo/bar.js")), - ]; - for (comment, path, request, expected) in data { - let resolved_path = resolver.resolve(&path, request).map(|r| r.full_path()); - assert_eq!(resolved_path, Ok(expected), "{comment} {path:?} {request}"); - } -} - #[test] fn resolve_edge_cases() { let f = super::fixture(); From 8e826e714e50e87155a038846e472687409f25ec Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 18 Nov 2025 00:29:44 +0800 Subject: [PATCH 12/17] perf: remove Result from `CachedPathImpl::canonicalized` (#847) 232 -> 144 bytes part of #846 --- src/cache/cache_impl.rs | 15 ++++++--------- src/cache/cached_path.rs | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/cache/cache_impl.rs b/src/cache/cache_impl.rs index b5edd8ac..768476cc 100644 --- a/src/cache/cache_impl.rs +++ b/src/cache/cache_impl.rs @@ -247,11 +247,9 @@ impl Cache { visited: &mut StdHashSet>, ) -> Result { // Check cache first - if this path was already canonicalized, return the cached result - if let Some(cached) = path.canonicalized.get() { - return cached.as_ref().map_err(Clone::clone).and_then(|weak| { - weak.upgrade().map(CachedPath).ok_or_else(|| { - io::Error::new(io::ErrorKind::NotFound, "Cached path no longer exists").into() - }) + if let Some(weak) = path.canonicalized.get() { + return weak.upgrade().map(CachedPath).ok_or_else(|| { + io::Error::new(io::ErrorKind::NotFound, "Cached path no longer exists").into() }); } @@ -292,15 +290,14 @@ impl Cache { Ok(normalized) }) }, - ); + )?; // Cache the result before removing from visited set // This ensures parent canonicalization results are cached and reused - path.canonicalized - .get_or_init(|| res.as_ref().map(|cp| Arc::downgrade(&cp.0)).map_err(Clone::clone)); + let _ = path.canonicalized.set(Arc::downgrade(&res.0)); // Remove from visited set when unwinding the recursion visited.remove(&path.hash); - res + Ok(res) } } diff --git a/src/cache/cached_path.rs b/src/cache/cached_path.rs index 8356de01..48f23e9b 100644 --- a/src/cache/cached_path.rs +++ b/src/cache/cached_path.rs @@ -27,7 +27,7 @@ pub struct CachedPathImpl { pub is_node_modules: bool, pub inside_node_modules: bool, pub meta: OnceLock>, - pub canonicalized: OnceLock, ResolveError>>, + pub canonicalized: OnceLock>, pub node_modules: OnceLock>>, pub package_json: OnceLock>>, pub tsconfig: OnceLock>>, From ea425f6158f5e6a4008e5d6b91070277dead83d2 Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 18 Nov 2025 07:39:35 +0000 Subject: [PATCH 13/17] perf: do not canonicalize the entry path (#848) This was introduced in `https://github.com/unrs/unrs-resolver/pull/125` The PR description and test case do not explain the reasoning behind this change, and I don't see how it reflects a real-world scenario in modern package managers. --- .../symlink-with-nested-node_modules/.gitignore | 1 - .../bar/node_modules/foo | 1 - .../foo/node_modules/dep/index.js | 0 .../foo/node_modules/foo/index.js | 0 src/lib.rs | 15 ++------------- src/tests/package_json.rs | 5 +++-- src/tests/resolve.rs | 16 ---------------- src/tests/symlink.rs | 5 +++-- 8 files changed, 8 insertions(+), 35 deletions(-) delete mode 100644 fixtures/symlink-with-nested-node_modules/.gitignore delete mode 120000 fixtures/symlink-with-nested-node_modules/bar/node_modules/foo delete mode 100644 fixtures/symlink-with-nested-node_modules/foo/node_modules/dep/index.js delete mode 100644 fixtures/symlink-with-nested-node_modules/foo/node_modules/foo/index.js diff --git a/fixtures/symlink-with-nested-node_modules/.gitignore b/fixtures/symlink-with-nested-node_modules/.gitignore deleted file mode 100644 index cf4bab9d..00000000 --- a/fixtures/symlink-with-nested-node_modules/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!node_modules diff --git a/fixtures/symlink-with-nested-node_modules/bar/node_modules/foo b/fixtures/symlink-with-nested-node_modules/bar/node_modules/foo deleted file mode 120000 index 99d688a4..00000000 --- a/fixtures/symlink-with-nested-node_modules/bar/node_modules/foo +++ /dev/null @@ -1 +0,0 @@ -../../foo/node_modules/foo \ No newline at end of file diff --git a/fixtures/symlink-with-nested-node_modules/foo/node_modules/dep/index.js b/fixtures/symlink-with-nested-node_modules/foo/node_modules/dep/index.js deleted file mode 100644 index e69de29b..00000000 diff --git a/fixtures/symlink-with-nested-node_modules/foo/node_modules/foo/index.js b/fixtures/symlink-with-nested-node_modules/foo/node_modules/foo/index.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/lib.rs b/src/lib.rs index 7f937e6c..5dcbae85 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -260,20 +260,9 @@ impl ResolverGeneric { ) -> Result { ctx.with_fully_specified(self.options.fully_specified); - let cached_path = if self.options.symlinks { - self.load_realpath(&self.cache.value(path))? - } else { - path.to_path_buf() - }; - - let cached_path = self.cache.value(&cached_path); + let cached_path = self.cache.value(path); let cached_path = self.require(&cached_path, specifier, ctx)?; - - let path = if self.options.symlinks { - self.load_realpath(&cached_path)? - } else { - cached_path.to_path_buf() - }; + let path = self.load_realpath(&cached_path)?; let package_json = self.find_package_json_for_a_package(&cached_path, ctx)?; if let Some(package_json) = &package_json { diff --git a/src/tests/package_json.rs b/src/tests/package_json.rs index 45643475..4b58e34f 100644 --- a/src/tests/package_json.rs +++ b/src/tests/package_json.rs @@ -1,6 +1,6 @@ //! Tests for `Resolution::package_json`. -use crate::{ResolveError, Resolver}; +use crate::Resolver; #[test] fn test() { @@ -68,8 +68,9 @@ fn package_json_with_symlinks_true() { fn test_corrupted_package_json() { use std::path::Path; + use crate::{ResolveError, ResolveOptions, ResolverGeneric}; + use super::memory_fs::MemoryFS; - use crate::{ResolveOptions, ResolverGeneric}; // Test scenarios for various corrupted package.json files let scenarios = [ diff --git a/src/tests/resolve.rs b/src/tests/resolve.rs index 5c630b71..8ea336af 100644 --- a/src/tests/resolve.rs +++ b/src/tests/resolve.rs @@ -165,22 +165,6 @@ fn resolve_dot() { } } -#[test] -fn symlink_with_nested_node_modules() { - let f = super::fixture_root().join("symlink-with-nested-node_modules"); - - let resolver = Resolver::default(); - let resolved_path = - resolver.resolve(f.join("bar/node_modules/foo"), "dep").map(|r| r.full_path()); - assert_eq!(resolved_path, Ok(f.join("foo/node_modules/dep/index.js"))); - - let resolver = Resolver::new(ResolveOptions { symlinks: false, ..ResolveOptions::default() }); - assert_eq!( - resolver.resolve(f.join("bar/node_modules/foo"), "dep"), - Err(ResolveError::NotFound("dep".into())) - ); -} - #[test] fn abnormal_relative() { let f = super::fixture_root().join("abnormal-relative-with-node_modules"); diff --git a/src/tests/symlink.rs b/src/tests/symlink.rs index f15e0084..24738fc7 100644 --- a/src/tests/symlink.rs +++ b/src/tests/symlink.rs @@ -174,7 +174,7 @@ fn test() { fn test_unsupported_targets() { use crate::ResolveError; - let Some(SymlinkFixturePaths { root: _, temp_path }) = + let Some(SymlinkFixturePaths { root, temp_path }) = prepare_symlinks("temp.test_unsupported_targets").unwrap() else { return; @@ -200,9 +200,10 @@ fn test_unsupported_targets() { // from `FsCachedPath::find_package_json` when trying to canonicalize the full path of `package.json`. // * Otherwise, a `ResolveError::NotFound` will be returned. let dos_device_temp_path = get_dos_device_path(&temp_path).unwrap(); + let dos_device_root = get_dos_device_path(&root).unwrap(); assert_eq!( resolver_with_symlinks.resolve(&dos_device_temp_path, "./index.js"), - Err(ResolveError::PathNotSupported(dos_device_temp_path)) + Err(ResolveError::PathNotSupported(dos_device_root)) ); } From 3a9d5e7c31d118781d8164a1b67c37a6bc26877b Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 18 Nov 2025 07:51:38 +0000 Subject: [PATCH 14/17] fix: do not resolve to `node_modules/pacakge/index` (#849) fixes #845 The option `main_files` is kind of confusing, it's supposed to be the file stem without the extension (e.g. index), but somehow it ended up being a lookup for `index` then `index.js` instead of just `index.js`. This reduces an extra "is file" system call for `node_modules/package/index`. --- src/lib.rs | 4 +- src/tests/alias.rs | 104 +++++++++++++++++------------------ src/tests/extension_alias.rs | 2 +- src/tests/fallback.rs | 72 ++++++++++++------------ src/tests/imports_field.rs | 2 +- src/tests/missing.rs | 1 - 6 files changed, 92 insertions(+), 93 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5dcbae85..41c3e59b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -756,7 +756,7 @@ impl ResolverGeneric { for main_file in &self.options.main_files { let cached_path = cached_path.normalize_with(main_file, self.cache.as_ref()); if self.options.enforce_extension.is_disabled() - && let Some(path) = self.load_alias_or_file(&cached_path, ctx)? + && let Some(path) = self.load_browser_field_or_alias(&cached_path, ctx)? && self.check_restrictions(path.path()) { return Ok(Some(path)); @@ -1515,7 +1515,7 @@ impl ResolverGeneric { .clone_with_options(ResolveOptions { tsconfig: None, extensions: vec![".json".into()], - main_files: vec!["tsconfig.json".into()], + main_files: vec!["tsconfig".into()], #[cfg(feature = "yarn_pnp")] yarn_pnp: self.options.yarn_pnp, #[cfg(feature = "yarn_pnp")] diff --git a/src/tests/alias.rs b/src/tests/alias.rs index 6d0c37a1..c7fda5b6 100644 --- a/src/tests/alias.rs +++ b/src/tests/alias.rs @@ -18,18 +18,18 @@ fn alias() { let f = Path::new("/"); let file_system = MemoryFS::new(&[ - ("/a/index", ""), - ("/a/dir/index", ""), - ("/recursive/index", ""), - ("/recursive/dir/index", ""), - ("/b/index", ""), - ("/b/dir/index", ""), - ("/c/index", ""), - ("/c/dir/index", ""), - ("/d/index.js", ""), + ("/a/index.js", ""), + ("/a/dir/index.js", ""), + ("/recursive/index.js", ""), + ("/recursive/dir/index.js", ""), + ("/b/index.js", ""), + ("/b/dir/index.js", ""), + ("/c/index.js", ""), + ("/c/dir/index.js", ""), + ("/d/index.js.js", ""), ("/d/dir/.empty", ""), - ("/e/index", ""), - ("/e/anotherDir/index", ""), + ("/e/index.js", ""), + ("/e/anotherDir/index.js", ""), ("/e/dir/file", ""), ("/dashed-name", ""), ]); @@ -39,8 +39,8 @@ fn alias() { ResolveOptions { alias: vec![ ("aliasA".into(), vec![AliasValue::from("a")]), - ("b$".into(), vec![AliasValue::from("a/index")]), - ("c$".into(), vec![AliasValue::from("/a/index")]), + ("b$".into(), vec![AliasValue::from("a/index.js")]), + ("c$".into(), vec![AliasValue::from("/a/index.js")]), ( "multiAlias".into(), vec![ @@ -53,7 +53,7 @@ fn alias() { ), ("recursive".into(), vec![AliasValue::from("recursive/dir")]), ("/d/dir".into(), vec![AliasValue::from("/c/dir")]), - ("/d/index.js".into(), vec![AliasValue::from("/c/index")]), + ("/d/index.js".into(), vec![AliasValue::from("/c/index.js")]), ("#".into(), vec![AliasValue::from("/c/dir")]), ("@".into(), vec![AliasValue::from("/c/dir")]), ("ignored".into(), vec![AliasValue::Ignore]), @@ -75,51 +75,51 @@ fn alias() { #[rustfmt::skip] let pass = [ - ("should resolve a not aliased module 1", "a", "/a/index"), - ("should resolve a not aliased module 2", "a/index", "/a/index"), - ("should resolve a not aliased module 3", "a/dir", "/a/dir/index"), - ("should resolve a not aliased module 4", "a/dir/index", "/a/dir/index"), - ("should resolve an aliased module 1", "aliasA", "/a/index"), - ("should resolve an aliased module 2", "aliasA/index", "/a/index"), - ("should resolve an aliased module 3", "aliasA/dir", "/a/dir/index"), - ("should resolve an aliased module 4", "aliasA/dir/index", "/a/dir/index"), - ("should resolve '#' alias 1", "#", "/c/dir/index"), - ("should resolve '#' alias 2", "#/index", "/c/dir/index"), - ("should resolve '@' alias 1", "@", "/c/dir/index"), - ("should resolve '@' alias 2", "@/index", "/c/dir/index"), - ("should resolve '@' alias 3", "@/", "/c/dir/index"), - ("should resolve a recursive aliased module 1", "recursive", "/recursive/dir/index"), - ("should resolve a recursive aliased module 2", "recursive/index", "/recursive/dir/index"), - ("should resolve a recursive aliased module 3", "recursive/dir", "/recursive/dir/index"), - ("should resolve a recursive aliased module 4", "recursive/dir/index", "/recursive/dir/index"), - ("should resolve a file aliased module 1", "b", "/a/index"), - ("should resolve a file aliased module 2", "c", "/a/index"), - ("should resolve a file aliased module with a query 1", "b?query", "/a/index?query"), - ("should resolve a file aliased module with a query 2", "c?query", "/a/index?query"), - ("should resolve a path in a file aliased module 1", "b/index", "/b/index"), - ("should resolve a path in a file aliased module 2", "b/dir", "/b/dir/index"), - ("should resolve a path in a file aliased module 3", "b/dir/index", "/b/dir/index"), - ("should resolve a path in a file aliased module 4", "c/index", "/c/index"), - ("should resolve a path in a file aliased module 5", "c/dir", "/c/dir/index"), - ("should resolve a path in a file aliased module 6", "c/dir/index", "/c/dir/index"), - ("should resolve a file aliased file 1", "d", "/c/index"), - ("should resolve a file aliased file 2", "d/dir/index", "/c/dir/index"), + ("should resolve a not aliased module 1", "a", "/a/index.js"), + ("should resolve a not aliased module 2", "a/index.js", "/a/index.js"), + ("should resolve a not aliased module 3", "a/dir", "/a/dir/index.js"), + ("should resolve a not aliased module 4", "a/dir/index.js", "/a/dir/index.js"), + ("should resolve an aliased module 1", "aliasA", "/a/index.js"), + ("should resolve an aliased module 2", "aliasA/index.js", "/a/index.js"), + ("should resolve an aliased module 3", "aliasA/dir", "/a/dir/index.js"), + ("should resolve an aliased module 4", "aliasA/dir/index.js", "/a/dir/index.js"), + ("should resolve '#' alias 1", "#", "/c/dir/index.js"), + ("should resolve '#' alias 2", "#/index.js", "/c/dir/index.js"), + ("should resolve '@' alias 1", "@", "/c/dir/index.js"), + ("should resolve '@' alias 2", "@/index.js", "/c/dir/index.js"), + ("should resolve '@' alias 3", "@/", "/c/dir/index.js"), + ("should resolve a recursive aliased module 1", "recursive", "/recursive/dir/index.js"), + ("should resolve a recursive aliased module 2", "recursive/index.js", "/recursive/dir/index.js"), + ("should resolve a recursive aliased module 3", "recursive/dir", "/recursive/dir/index.js"), + ("should resolve a recursive aliased module 4", "recursive/dir/index.js", "/recursive/dir/index.js"), + ("should resolve a file aliased module 1", "b", "/a/index.js"), + ("should resolve a file aliased module 2", "c", "/a/index.js"), + ("should resolve a file aliased module with a query 1", "b?query", "/a/index.js?query"), + ("should resolve a file aliased module with a query 2", "c?query", "/a/index.js?query"), + ("should resolve a path in a file aliased module 1", "b/index.js", "/b/index.js"), + ("should resolve a path in a file aliased module 2", "b/dir", "/b/dir/index.js"), + ("should resolve a path in a file aliased module 3", "b/dir/index.js", "/b/dir/index.js"), + ("should resolve a path in a file aliased module 4", "c/index.js", "/c/index.js"), + ("should resolve a path in a file aliased module 5", "c/dir", "/c/dir/index.js"), + ("should resolve a path in a file aliased module 6", "c/dir/index.js", "/c/dir/index.js"), + ("should resolve a file aliased file 1", "d", "/c/index.js"), + ("should resolve a file aliased file 2", "d/dir/index.js", "/c/dir/index.js"), ("should resolve a file in multiple aliased dirs 1", "multiAlias/dir/file", "/e/dir/file"), - ("should resolve a file in multiple aliased dirs 2", "multiAlias/anotherDir", "/e/anotherDir/index"), + ("should resolve a file in multiple aliased dirs 2", "multiAlias/anotherDir", "/e/anotherDir/index.js"), // wildcard - ("should resolve wildcard alias 1", "@a", "/a/index"), - ("should resolve wildcard alias 2", "@a/dir", "/a/dir/index"), + ("should resolve wildcard alias 1", "@a", "/a/index.js"), + ("should resolve wildcard alias 2", "@a/dir", "/a/dir/index.js"), ("should resolve wildcard alias 3", "@e/dir/file", "/e/dir/file"), - ("should resolve wildcard alias 4", "@e/anotherDir", "/e/anotherDir/index"), + ("should resolve wildcard alias 4", "@e/anotherDir", "/e/anotherDir/index.js"), ("should resolve wildcard alias 5", "@e/dir/file", "/e/dir/file"), // added to test value without wildcard - ("should resolve scoped package name with sub dir 1", "@adir/index", "/a/index"), - ("should resolve scoped package name with sub dir 2", "@adir/dir", "/a/index"), + ("should resolve scoped package name with sub dir 1", "@adir/index.js", "/a/index.js"), + ("should resolve scoped package name with sub dir 2", "@adir/dir", "/a/index.js"), // not part of enhanced-resolve, added to make sure query in alias value works - ("should resolve query in alias value", "alias_query?query_before", "/a/index?query_after"), - ("should resolve query in alias value", "alias_fragment#fragment_before", "/a/index#fragment_after"), + ("should resolve query in alias value", "alias_query?query_before", "/a/index.js?query_after"), + ("should resolve query in alias value", "alias_fragment#fragment_before", "/a/index.js#fragment_after"), ("should resolve dashed name", "dashed-name", "/dashed-name"), - ("should resolve scoped package name with sub dir", "@scope/package-name/file", "/c/dir/index"), + ("should resolve scoped package name with sub dir", "@scope/package-name/file", "/c/dir/index.js"), ]; for (comment, request, expected) in pass { diff --git a/src/tests/extension_alias.rs b/src/tests/extension_alias.rs index 43f2f075..4978bc1c 100644 --- a/src/tests/extension_alias.rs +++ b/src/tests/extension_alias.rs @@ -57,7 +57,7 @@ fn not_apply_to_extension_nor_main_files() { let resolver = Resolver::new(ResolveOptions { extensions: vec![".js".into()], - main_files: vec!["index.js".into()], + main_files: vec!["index".into()], extension_alias: vec![(".js".into(), vec![])], ..ResolveOptions::default() }); diff --git a/src/tests/fallback.rs b/src/tests/fallback.rs index c5bd4e76..8dccc3c8 100644 --- a/src/tests/fallback.rs +++ b/src/tests/fallback.rs @@ -11,20 +11,20 @@ fn fallback() { let f = Path::new("/"); let file_system = MemoryFS::new(&[ - ("/a/index", ""), - ("/a/dir/index", ""), - ("/recursive/index", ""), - ("/recursive/dir/index", ""), + ("/a/index.js", ""), + ("/a/dir/index.js", ""), + ("/recursive/index.js", ""), + ("/recursive/dir/index.js", ""), ("/recursive/dir/file", ""), - ("/recursive/dir/dir/index", ""), - ("/b/index", ""), - ("/b/dir/index", ""), - ("/c/index", ""), - ("/c/dir/index", ""), - ("/d/index.js", ""), + ("/recursive/dir/dir/index.js", ""), + ("/b/index.js", ""), + ("/b/dir/index.js", ""), + ("/c/index.js", ""), + ("/c/dir/index.js", ""), + ("/d/index.js.js", ""), ("/d/dir/.empty", ""), - ("/e/index", ""), - ("/e/anotherDir/index", ""), + ("/e/index.js", ""), + ("/e/anotherDir/index.js", ""), ("/e/dir/file", ""), ]); @@ -33,8 +33,8 @@ fn fallback() { ResolveOptions { fallback: vec![ ("aliasA".into(), vec![AliasValue::Path("a".into())]), - ("b$".into(), vec![AliasValue::Path("a/index".into())]), - ("c$".into(), vec![AliasValue::Path("/a/index".into())]), + ("b$".into(), vec![AliasValue::Path("a/index.js".into())]), + ("c$".into(), vec![AliasValue::Path("/a/index.js".into())]), ( "multiAlias".into(), vec![ @@ -47,7 +47,7 @@ fn fallback() { ), ("recursive".into(), vec![AliasValue::Path("recursive/dir".into())]), ("/d/dir".into(), vec![AliasValue::Path("/c/dir".into())]), - ("/d/index.js".into(), vec![AliasValue::Path("/c/index".into())]), + ("/d/index.js.js".into(), vec![AliasValue::Path("/c/index.js".into())]), ("ignored".into(), vec![AliasValue::Ignore]), ("node:path".into(), vec![AliasValue::Ignore]), ], @@ -58,29 +58,29 @@ fn fallback() { #[rustfmt::skip] let pass = [ - ("should resolve a not aliased module 1", "a", "/a/index"), - ("should resolve a not aliased module 2", "a/index", "/a/index"), - ("should resolve a not aliased module 3", "a/dir", "/a/dir/index"), - ("should resolve a not aliased module 4", "a/dir/index", "/a/dir/index"), - ("should resolve an fallback module 1", "aliasA", "/a/index"), - ("should resolve an fallback module 2", "aliasA/index", "/a/index"), - ("should resolve an fallback module 3", "aliasA/dir", "/a/dir/index"), - ("should resolve an fallback module 4", "aliasA/dir/index", "/a/dir/index"), - ("should resolve a recursive aliased module 1", "recursive", "/recursive/index"), - ("should resolve a recursive aliased module 2", "recursive/index", "/recursive/index"), - ("should resolve a recursive aliased module 3", "recursive/dir", "/recursive/dir/index"), - ("should resolve a recursive aliased module 4", "recursive/dir/index", "/recursive/dir/index"), + ("should resolve a not aliased module 1", "a", "/a/index.js"), + ("should resolve a not aliased module 2", "a/index.js", "/a/index.js"), + ("should resolve a not aliased module 3", "a/dir", "/a/dir/index.js"), + ("should resolve a not aliased module 4", "a/dir/index.js", "/a/dir/index.js"), + ("should resolve an fallback module 1", "aliasA", "/a/index.js"), + ("should resolve an fallback module 2", "aliasA/index.js", "/a/index.js"), + ("should resolve an fallback module 3", "aliasA/dir", "/a/dir/index.js"), + ("should resolve an fallback module 4", "aliasA/dir/index.js", "/a/dir/index.js"), + ("should resolve a recursive aliased module 1", "recursive", "/recursive/index.js"), + ("should resolve a recursive aliased module 2", "recursive/index.js", "/recursive/index.js"), + ("should resolve a recursive aliased module 3", "recursive/dir", "/recursive/dir/index.js"), + ("should resolve a recursive aliased module 4", "recursive/dir/index.js", "/recursive/dir/index.js"), ("should resolve a recursive aliased module 5", "recursive/file", "/recursive/dir/file"), - ("should resolve a file aliased module with a query 1", "b?query", "/b/index?query"), - ("should resolve a file aliased module with a query 2", "c?query", "/c/index?query"), - ("should resolve a path in a file aliased module 1", "b/index", "/b/index"), - ("should resolve a path in a file aliased module 2", "b/dir", "/b/dir/index"), - ("should resolve a path in a file aliased module 3", "b/dir/index", "/b/dir/index"), - ("should resolve a path in a file aliased module 4", "c/index", "/c/index"), - ("should resolve a path in a file aliased module 5", "c/dir", "/c/dir/index"), - ("should resolve a path in a file aliased module 6", "c/dir/index", "/c/dir/index"), + ("should resolve a file aliased module with a query 1", "b?query", "/b/index.js?query"), + ("should resolve a file aliased module with a query 2", "c?query", "/c/index.js?query"), + ("should resolve a path in a file aliased module 1", "b/index.js", "/b/index.js"), + ("should resolve a path in a file aliased module 2", "b/dir", "/b/dir/index.js"), + ("should resolve a path in a file aliased module 3", "b/dir/index.js", "/b/dir/index.js"), + ("should resolve a path in a file aliased module 4", "c/index.js", "/c/index.js"), + ("should resolve a path in a file aliased module 5", "c/dir", "/c/dir/index.js"), + ("should resolve a path in a file aliased module 6", "c/dir/index.js", "/c/dir/index.js"), ("should resolve a file in multiple aliased dirs 1", "multiAlias/dir/file", "/e/dir/file"), - ("should resolve a file in multiple aliased dirs 2", "multiAlias/anotherDir", "/e/anotherDir/index"), + ("should resolve a file in multiple aliased dirs 2", "multiAlias/anotherDir", "/e/anotherDir/index.js"), ]; for (comment, request, expected) in pass { diff --git a/src/tests/imports_field.rs b/src/tests/imports_field.rs index 7ec62429..95a34344 100644 --- a/src/tests/imports_field.rs +++ b/src/tests/imports_field.rs @@ -15,7 +15,7 @@ fn test_simple() { let resolver = Resolver::new(ResolveOptions { extensions: vec![".js".into()], - main_files: vec!["index.js".into()], + main_files: vec!["index".into()], condition_names: vec!["webpack".into()], ..ResolveOptions::default() }); diff --git a/src/tests/missing.rs b/src/tests/missing.rs index 0a284f5d..28f2d509 100644 --- a/src/tests/missing.rs +++ b/src/tests/missing.rs @@ -37,7 +37,6 @@ fn test() { ( "m1/", vec![ - f.join("node_modules/m1/index"), f.join("node_modules/m1/index.js"), f.join("node_modules/m1/index.json"), f.join("node_modules/m1/index.node"), From be1e1b4712858f6f3da3e511d61300e91ef7d58f Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 18 Nov 2025 08:40:21 +0000 Subject: [PATCH 15/17] refactor: do not store is_symlink in CachedPathImpl (#850) `std::fs::metadata` always return `is_symlink: false` so it's confusing and pointless to store it in CachedPathImpl --- examples/many.rs | 3 --- src/cache/cache_impl.rs | 8 ++++---- src/cache/cached_path.rs | 17 ++++++++++++----- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/examples/many.rs b/examples/many.rs index da5690b3..420e120c 100644 --- a/examples/many.rs +++ b/examples/many.rs @@ -52,10 +52,7 @@ fn main() { } } - // Initialize resolver let options = ResolveOptions { - alias_fields: vec![vec!["browser".into()]], - // ESM condition_names: vec!["node".into(), "import".into()], ..ResolveOptions::default() }; diff --git a/src/cache/cache_impl.rs b/src/cache/cache_impl.rs index 768476cc..8d63f7c7 100644 --- a/src/cache/cache_impl.rs +++ b/src/cache/cache_impl.rs @@ -79,9 +79,9 @@ impl Cache { } pub(crate) fn is_file(&self, path: &CachedPath, ctx: &mut Ctx) -> bool { - if let Some(meta) = path.meta(&self.fs) { + if path.is_file(&self.fs).is_some_and(|b| b) { ctx.add_file_dependency(path.path()); - meta.is_file + true } else { ctx.add_missing_dependency(path.path()); false @@ -89,12 +89,12 @@ impl Cache { } pub(crate) fn is_dir(&self, path: &CachedPath, ctx: &mut Ctx) -> bool { - path.meta(&self.fs).map_or_else( + path.is_dir(&self.fs).map_or_else( || { ctx.add_missing_dependency(path.path()); false }, - |meta| meta.is_dir, + |b| b, ) } diff --git a/src/cache/cached_path.rs b/src/cache/cached_path.rs index 48f23e9b..3222798f 100644 --- a/src/cache/cached_path.rs +++ b/src/cache/cached_path.rs @@ -13,8 +13,7 @@ use once_cell::sync::OnceCell as OnceLock; use super::cache_impl::Cache; use super::thread_local::SCRATCH_PATH; use crate::{ - FileMetadata, FileSystem, PackageJson, ResolveError, ResolveOptions, TsConfig, - context::ResolveContext as Ctx, + FileSystem, PackageJson, ResolveError, ResolveOptions, TsConfig, context::ResolveContext as Ctx, }; #[derive(Clone)] @@ -26,7 +25,7 @@ pub struct CachedPathImpl { pub parent: Option>, pub is_node_modules: bool, pub inside_node_modules: bool, - pub meta: OnceLock>, + pub meta: OnceLock>, // None means not found. pub canonicalized: OnceLock>, pub node_modules: OnceLock>>, pub package_json: OnceLock>>, @@ -226,8 +225,16 @@ impl CachedPath { } impl CachedPath { - pub(crate) fn meta(&self, fs: &Fs) -> Option { - *self.meta.get_or_init(|| fs.metadata(&self.path).ok()) + fn metadata(&self, fs: &Fs) -> Option<(bool, bool)> { + *self.meta.get_or_init(|| fs.metadata(&self.path).ok().map(|r| (r.is_file, r.is_dir))) + } + + pub(crate) fn is_file(&self, fs: &Fs) -> Option { + self.metadata(fs).map(|r| r.0) + } + + pub(crate) fn is_dir(&self, fs: &Fs) -> Option { + self.metadata(fs).map(|r| r.1) } } From 15e1481f326b13763f78c186cb5732ad3dfd3eee Mon Sep 17 00:00:00 2001 From: Boshen Date: Wed, 19 Nov 2025 07:35:59 +0000 Subject: [PATCH 16/17] refactor: use RwLock> for package.json storage (#838) --- Cargo.lock | 39 +++++++++++++++++++++++++ Cargo.toml | 1 + src/cache/cache_impl.rs | 60 +++++++++++++++++++++++++-------------- src/cache/cached_path.rs | 3 +- src/package_json/mod.rs | 11 +++++-- src/package_json/serde.rs | 2 +- src/package_json/simd.rs | 2 +- src/tests/dependencies.rs | 22 +++++++------- 8 files changed, 100 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1cee52dc..fc520936 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -799,6 +799,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "memchr" version = "2.7.6" @@ -950,6 +959,7 @@ dependencies = [ "json-strip-comments", "once_cell", "papaya", + "parking_lot", "pico-args", "pnp", "rayon", @@ -992,6 +1002,29 @@ dependencies = [ "seize", ] +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + [[package]] name = "pathdiff" version = "0.2.3" @@ -1200,6 +1233,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "seize" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 20128837..1facff86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,6 +82,7 @@ indexmap = { version = "2", features = ["serde"] } json-strip-comments = "3" once_cell = "1" # Use `std::sync::OnceLock::get_or_try_init` when it is stable. papaya = "0.2" +parking_lot = "0.12" rustc-hash = { version = "2" } serde = { version = "1", features = ["derive"] } # derive for Deserialize from package.json serde_json = { version = "1", features = ["preserve_order"] } # preserve_order: package_json.exports requires order such as `["require", "import", "default"]` diff --git a/src/cache/cache_impl.rs b/src/cache/cache_impl.rs index 8d63f7c7..4f701358 100644 --- a/src/cache/cache_impl.rs +++ b/src/cache/cache_impl.rs @@ -11,6 +11,7 @@ use cfg_if::cfg_if; #[cfg(feature = "yarn_pnp")] use once_cell::sync::OnceCell; use papaya::{HashMap, HashSet}; +use parking_lot::RwLock; use rustc_hash::FxHasher; use super::borrowed_path::BorrowedCachedPath; @@ -21,11 +22,14 @@ use crate::{ context::ResolveContext as Ctx, path::PathUtil, }; +pub type PackageJsonIndex = usize; + /// Cache implementation used for caching filesystem access. #[derive(Default)] pub struct Cache { pub(crate) fs: Fs, pub(crate) paths: HashSet>, + pub(crate) package_jsons: RwLock>>, pub(crate) tsconfigs: HashMap, BuildHasherDefault>, #[cfg(feature = "yarn_pnp")] pub(crate) yarn_pnp_manifest: OnceCell, @@ -35,6 +39,7 @@ impl Cache { pub fn clear(&self) { self.paths.pin().clear(); self.tsconfigs.pin().clear(); + self.package_jsons.write().clear(); } #[allow(clippy::cast_possible_truncation)] @@ -110,38 +115,48 @@ impl Cache { .get_or_try_init(|| { let package_json_path = path.path.join("package.json"); let Ok(package_json_bytes) = self.fs.read(&package_json_path) else { + if let Some(deps) = &mut ctx.missing_dependencies { + deps.push(package_json_path); + } return Ok(None); }; - let real_path = if options.symlinks { self.canonicalize(path)?.join("package.json") } else { package_json_path.clone() }; - PackageJson::parse(&self.fs, package_json_path, real_path, package_json_bytes) - .map(|package_json| Some(Arc::new(package_json))) - .map_err(ResolveError::Json) + PackageJson::parse( + &self.fs, + package_json_path.clone(), + real_path, + package_json_bytes, + ) + .map(|package_json| { + let arc = Arc::new(package_json); + let index = { + let mut arena = self.package_jsons.write(); + let index = arena.len(); + arena.push(arc); + index + }; + Some(index) + }) + .map_err(ResolveError::Json) + // https://github.com/webpack/enhanced-resolve/blob/58464fc7cb56673c9aa849e68e6300239601e615/lib/DescriptionFileUtils.js#L68-L82 + .inspect(|_| { + ctx.add_file_dependency(&package_json_path); + }) + .inspect_err(|_| { + if let Some(deps) = &mut ctx.file_dependencies { + deps.push(package_json_path.clone()); + } + }) }) .cloned(); - // https://github.com/webpack/enhanced-resolve/blob/58464fc7cb56673c9aa849e68e6300239601e615/lib/DescriptionFileUtils.js#L68-L82 - match &result { - Ok(Some(package_json)) => { - ctx.add_file_dependency(&package_json.path); - } - Ok(None) => { - // Avoid an allocation by making this lazy - if let Some(deps) = &mut ctx.missing_dependencies { - deps.push(path.path.join("package.json")); - } - } - Err(_) => { - if let Some(deps) = &mut ctx.file_dependencies { - deps.push(path.path.join("package.json")); - } - } - } - result + result.map(|option_index| { + option_index.and_then(|index| self.package_jsons.read().get(index).cloned()) + }) } pub(crate) fn get_tsconfig Result<(), ResolveError>>( @@ -213,6 +228,7 @@ impl Cache { .hasher(BuildHasherDefault::default()) .resize_mode(papaya::ResizeMode::Blocking) .build(), + package_jsons: RwLock::new(Vec::with_capacity(512)), tsconfigs: HashMap::builder() .hasher(BuildHasherDefault::default()) .resize_mode(papaya::ResizeMode::Blocking) diff --git a/src/cache/cached_path.rs b/src/cache/cached_path.rs index 3222798f..962a2d9c 100644 --- a/src/cache/cached_path.rs +++ b/src/cache/cached_path.rs @@ -11,6 +11,7 @@ use cfg_if::cfg_if; use once_cell::sync::OnceCell as OnceLock; use super::cache_impl::Cache; +use super::cache_impl::PackageJsonIndex; use super::thread_local::SCRATCH_PATH; use crate::{ FileSystem, PackageJson, ResolveError, ResolveOptions, TsConfig, context::ResolveContext as Ctx, @@ -28,7 +29,7 @@ pub struct CachedPathImpl { pub meta: OnceLock>, // None means not found. pub canonicalized: OnceLock>, pub node_modules: OnceLock>>, - pub package_json: OnceLock>>, + pub package_json: OnceLock>, pub tsconfig: OnceLock>>, } diff --git a/src/package_json/mod.rs b/src/package_json/mod.rs index 9377b84d..4c867420 100644 --- a/src/package_json/mod.rs +++ b/src/package_json/mod.rs @@ -14,15 +14,20 @@ pub use serde::*; #[cfg(target_endian = "little")] pub use simd::*; -use std::{fmt, path::PathBuf}; +use std::{fmt, path::Path}; use crate::JSONError; /// Check if JSON content is empty or contains only whitespace -fn check_if_empty(json_bytes: &[u8], path: PathBuf) -> Result<(), JSONError> { +fn check_if_empty(json_bytes: &[u8], path: &Path) -> Result<(), JSONError> { // Check if content is empty or whitespace-only if json_bytes.iter().all(|&b| b.is_ascii_whitespace()) { - return Err(JSONError { path, message: "File is empty".to_string(), line: 0, column: 0 }); + return Err(JSONError { + path: path.to_path_buf(), + message: "File is empty".to_string(), + line: 0, + column: 0, + }); } Ok(()) } diff --git a/src/package_json/serde.rs b/src/package_json/serde.rs index 17f87cd5..73291c89 100644 --- a/src/package_json/serde.rs +++ b/src/package_json/serde.rs @@ -230,7 +230,7 @@ impl PackageJson { let json_bytes = if json.starts_with(b"\xEF\xBB\xBF") { &json[3..] } else { &json[..] }; // Check if empty after BOM stripping - super::check_if_empty(json_bytes, path.clone())?; + super::check_if_empty(json_bytes, &path)?; // Parse JSON directly from bytes let value = serde_json::from_slice::(json_bytes).map_err(|error| JSONError { diff --git a/src/package_json/simd.rs b/src/package_json/simd.rs index 92b8c7da..373c643d 100644 --- a/src/package_json/simd.rs +++ b/src/package_json/simd.rs @@ -269,7 +269,7 @@ impl PackageJson { } // Check if empty after BOM stripping - super::check_if_empty(&json_bytes, path.clone())?; + super::check_if_empty(&json_bytes, &path)?; // Create the self-cell with the JSON bytes and parsed BorrowedValue let cell = PackageJsonCell::try_new(MutBorrow::new(json_bytes), |bytes| { diff --git a/src/tests/dependencies.rs b/src/tests/dependencies.rs index ee4e441e..02f0d946 100644 --- a/src/tests/dependencies.rs +++ b/src/tests/dependencies.rs @@ -1,7 +1,7 @@ //! https://github.com/webpack/enhanced-resolve/blob/main/test/dependencies.test.js #[cfg(not(target_os = "windows"))] // MemoryFS's path separator is always `/` so the test will not pass in windows. -mod windows { +mod test { use std::path::PathBuf; use super::super::memory_fs::MemoryFS; @@ -18,17 +18,6 @@ mod windows { #[test] fn test() { - let file_system = file_system(); - - let resolver = ResolverGeneric::new_with_file_system( - file_system, - ResolveOptions { - extensions: vec![".json".into(), ".js".into()], - modules: vec!["/modules".into(), "node_modules".into()], - ..ResolveOptions::default() - }, - ); - let data = [ ( "middle module request", @@ -92,6 +81,15 @@ mod windows { ]; for (name, context, request, result, file_dependencies, missing_dependencies) in data { + let file_system = file_system(); + let resolver = ResolverGeneric::new_with_file_system( + file_system, + ResolveOptions { + extensions: vec![".json".into(), ".js".into()], + modules: vec!["/modules".into(), "node_modules".into()], + ..ResolveOptions::default() + }, + ); let mut ctx = ResolveContext::default(); let path = PathBuf::from(context); let resolved_path = From a67f304fbec7088bd298cf6f3fc67966642f0246 Mon Sep 17 00:00:00 2001 From: Boshen Date: Wed, 19 Nov 2025 07:36:00 +0000 Subject: [PATCH 17/17] perf: cache all package.json resolutions for faster package.json lookup (#853) Previously `find_package_json` needs to traverse up path parents, which involves a lot of `once_cell.get_or_try_init()` calls. --- src/cache/cache_impl.rs | 64 +++++++++++++++++++++++++++++++++++----- src/cache/cached_path.rs | 34 +-------------------- src/lib.rs | 13 ++++---- 3 files changed, 62 insertions(+), 49 deletions(-) diff --git a/src/cache/cache_impl.rs b/src/cache/cache_impl.rs index 4f701358..ad2e35d5 100644 --- a/src/cache/cache_impl.rs +++ b/src/cache/cache_impl.rs @@ -103,22 +103,74 @@ impl Cache { ) } + /// Get package.json of a path of `path`. + /// + /// # Errors + /// + /// * [ResolveError::Json] pub(crate) fn get_package_json( &self, path: &CachedPath, options: &ResolveOptions, ctx: &mut Ctx, ) -> Result>, ResolveError> { + self.find_package_json(path, options, ctx).map(|option_package_json| { + option_package_json.filter(|package_json| { + package_json + .path() + .parent() + .is_some_and(|p| p.as_os_str() == path.path().as_os_str()) + }) + }) + } + + /// Find package.json of a path by traversing parent directories. + /// + /// # Errors + /// + /// * [ResolveError::Json] + pub(crate) fn find_package_json( + &self, + path: &CachedPath, + options: &ResolveOptions, + ctx: &mut Ctx, + ) -> Result>, ResolveError> { + let mut path = path.clone(); + // Go up directories when the querying path is not a directory + while !self.is_dir(&path, ctx) { + if let Some(cv) = path.parent() { + path = cv; + } else { + break; + } + } + self.find_package_json_impl(&path, options, ctx).map(|option_index| { + option_index.and_then(|index| self.package_jsons.read().get(index).cloned()) + }) + } + + /// Find package.json of a path by traversing parent directories. + /// + /// # Errors + /// + /// * [ResolveError::Json] + fn find_package_json_impl( + &self, + path: &CachedPath, + options: &ResolveOptions, + ctx: &mut Ctx, + ) -> Result, ResolveError> { // Change to `std::sync::OnceLock::get_or_try_init` when it is stable. - let result = path - .package_json + path.package_json .get_or_try_init(|| { let package_json_path = path.path.join("package.json"); let Ok(package_json_bytes) = self.fs.read(&package_json_path) else { if let Some(deps) = &mut ctx.missing_dependencies { deps.push(package_json_path); } - return Ok(None); + return path.parent().map_or(Ok(None), |parent| { + self.find_package_json_impl(&parent, options, ctx) + }); }; let real_path = if options.symlinks { self.canonicalize(path)?.join("package.json") @@ -152,11 +204,7 @@ impl Cache { } }) }) - .cloned(); - - result.map(|option_index| { - option_index.and_then(|index| self.package_jsons.read().get(index).cloned()) - }) + .cloned() } pub(crate) fn get_tsconfig Result<(), ResolveError>>( diff --git a/src/cache/cached_path.rs b/src/cache/cached_path.rs index 962a2d9c..430101d1 100644 --- a/src/cache/cached_path.rs +++ b/src/cache/cached_path.rs @@ -13,9 +13,7 @@ use once_cell::sync::OnceCell as OnceLock; use super::cache_impl::Cache; use super::cache_impl::PackageJsonIndex; use super::thread_local::SCRATCH_PATH; -use crate::{ - FileSystem, PackageJson, ResolveError, ResolveOptions, TsConfig, context::ResolveContext as Ctx, -}; +use crate::{FileSystem, TsConfig, context::ResolveContext as Ctx}; #[derive(Clone)] pub struct CachedPath(pub Arc); @@ -108,36 +106,6 @@ impl CachedPath { .and_then(|weak| weak.upgrade().map(CachedPath)) } - /// Find package.json of a path by traversing parent directories. - /// - /// # Errors - /// - /// * [ResolveError::Json] - pub(crate) fn find_package_json( - &self, - options: &ResolveOptions, - cache: &Cache, - ctx: &mut Ctx, - ) -> Result>, ResolveError> { - let mut cache_value = self.clone(); - // Go up directories when the querying path is not a directory - while !cache.is_dir(&cache_value, ctx) { - if let Some(cv) = cache_value.parent() { - cache_value = cv; - } else { - break; - } - } - let mut cache_value = Some(cache_value); - while let Some(cv) = cache_value { - if let Some(package_json) = cache.get_package_json(&cv, options, ctx)? { - return Ok(Some(package_json)); - } - cache_value = cv.parent(); - } - Ok(None) - } - pub(crate) fn add_extension(&self, ext: &str, cache: &Cache) -> Self { SCRATCH_PATH.with_borrow_mut(|path| { path.clear(); diff --git a/src/lib.rs b/src/lib.rs index 41c3e59b..f003f012 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -304,7 +304,7 @@ impl ResolverGeneric { } Ok(last) } else { - cached_path.find_package_json(&self.options, self.cache.as_ref(), ctx) + self.cache.find_package_json(cached_path, &self.options, ctx) } } @@ -594,8 +594,7 @@ impl ResolverGeneric { ) -> ResolveResult { // 1. Find the closest package scope SCOPE to DIR. // 2. If no scope was found, return. - let Some(package_json) = - cached_path.find_package_json(&self.options, self.cache.as_ref(), ctx)? + let Some(package_json) = self.cache.find_package_json(cached_path, &self.options, ctx)? else { return Ok(None); }; @@ -778,7 +777,7 @@ impl ResolverGeneric { ) -> ResolveResult { if !self.options.alias_fields.is_empty() && let Some(package_json) = - cached_path.find_package_json(&self.options, self.cache.as_ref(), ctx)? + self.cache.find_package_json(cached_path, &self.options, ctx)? && let Some(path) = self.load_browser_field(cached_path, None, &package_json, ctx)? { return Ok(Some(path)); @@ -1030,8 +1029,7 @@ impl ResolverGeneric { ) -> ResolveResult { // 1. Find the closest package scope SCOPE to DIR. // 2. If no scope was found, return. - let Some(package_json) = - cached_path.find_package_json(&self.options, self.cache.as_ref(), ctx)? + let Some(package_json) = self.cache.find_package_json(cached_path, &self.options, ctx)? else { return Ok(None); }; @@ -2104,8 +2102,7 @@ impl ResolverGeneric { Some("js" | "ts") => { // 7. Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(url). // 8. Let pjson be the result of READ_PACKAGE_JSON(packageURL). - let package_json = - cached_path.find_package_json(&self.options, self.cache.as_ref(), ctx)?; + let package_json = self.cache.find_package_json(cached_path, &self.options, ctx)?; // 9. Let packageType be null. if let Some(package_json) = package_json { // 10. If pjson?.type is "module" or "commonjs", then