refactor: remove dead code and redundant work#1263
Conversation
- Remove the never-true `i == targets.len()` branch in `package_target_resolve` array handling (`i` comes from `enumerate()` so it maxes out at `len - 1`) and correct the comment to describe the actual fall-through behavior. - Compile `fallback` aliases once at construction instead of running `compile_alias` on every failed resolution; delete the now-unused `load_alias_by_options`. - Skip the `TsConfig` deep clone in `Cache::get_tsconfig` on the non-root (`extends`) path where it was dropped unused. - Factor the duplicated typings/types/main entry selection in `dts_resolve_as_directory` into `dts_package_entry`. - Remove dead code: `impl BitOr for Extensions`, unused `_cached_path` parameter, napi `EnforceExtension` helpers with no callers, a no-op `let _ = meta` in a test. - Simplify: derive `Resolution::clone`, merge duplicate #[cold] error constructors in `Specifier::parse`, `ok_or_else` in `require_hash`, plain equality for the yarn_pnp cache check in `clone_with_options`, drop a redundant `.as_ref()` and a `Some(x).as_deref().unwrap()` dance. - Fix stale doc comment on `TsConfig::root` (template variable substitution is driven by `should_build` now).
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1263 +/- ##
==========================================
+ Coverage 93.85% 93.96% +0.10%
==========================================
Files 21 21
Lines 4313 4272 -41
==========================================
- Hits 4048 4014 -34
+ Misses 265 258 -7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Merging this PR will degrade performance by 4.23%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
`load_alias_by_options` re-ran `compile_alias` (allocating and cloning every `AliasValue`) on **every failed resolution**, while the primary `alias` list is compiled once at construction. This compiles `fallback` once into a `ResolverImpl.fallback` field, uses `load_alias` directly at the fallback call site, and deletes `load_alias_by_options` (its only caller). `compile_alias` is pure over the post-`sanitize` options, so behavior is identical; with an empty fallback list the new field is an empty box + 32 zero bytes. Also tidies `clone_with_options` while touching it: the `(a && !b) || (!a && b)` yarn_pnp cache check becomes a plain `==` comparison, and the stale `#[allow(clippy::unused_self)]` is removed (both cfg branches use `self`). Split out of #1263.
) `Cache::get_tsconfig` deep-cloned every parsed `TsConfig` before branching on `root`, but the clone only matters in the root branch, where `TsConfig::build(mut self)` consumes the value after the raw version is cached. On the non-root path — taken once per `extends` entry — the original local was dropped unused, so the clone (`CompilerOptions`, three `Option<Vec<PathBuf>>`s, references, paths) was pure waste. The raw cache still stores the `should_build = false` version and the built cache still stores the built version; returned `Arc`s share the cached instances exactly as before. Split out of #1263.
…de (#1266) - Factor the byte-identical 14-line `typings`/`types`/`main` entry-selection block, which appeared twice in `dts_resolve_as_directory` (once in the `typesVersions` branch, once in the types/typings/main branch), into a `dts_package_entry` helper, and collapse the resulting nested `if let` into a let-chain. - Remove `impl BitOr for Extensions`: the `|` operator is never invoked on this private type — every union goes through `.union()` (`BitAnd` is used and stays). - Drop the unused `_cached_path` parameter from `dts_resolve_tsconfig_paths` (private method, single caller). Split out of #1263.
A batch of tiny, independent cleanups:
- Derive `Clone` for `Resolution` — the manual impl was field-for-field
identical to what the derive produces (`Debug`/`PartialEq` stay manual,
they're genuinely custom).
- Merge the two byte-identical `#[cold]` empty-error constructors in
`Specifier::parse` into one.
- `require_hash`: `.ok_or_else(..)` instead of `.map_or_else(|| Err(..),
Ok)`.
- Remove a pointless `Some(owned).as_deref().unwrap()` dance in the
legacy `jest-runner-../..` fallback path.
- Drop a redundant `.as_ref()` on `file_name()` in `Cache::value`
(`&OsStr == &str` already works via `OsStr: PartialEq<str>`).
- Remove the napi `EnforceExtension::{is_auto,is_enabled,is_disabled}`
helpers — zero callers anywhere in the repo and not `#[napi]`-exported,
so they never reached JS.
- Remove a no-op `let _ = meta;` in the `metadata` test.
- Fix the stale doc comment on `TsConfig::root` / `root()": it claimed
the field drives final template-variable substitution, but that's keyed
off `should_build` now; `root` just records whether the config is the
caller's (vs loaded through `extends`).
Split out of #1263.
) The "return the last array entry's error" branch in `package_target_resolve` was dead code: `i` comes from `enumerate()`, so `i == targets.len()` could never be true. Errors from array entries were always swallowed like `undefined`, so an invalid target in the last fallback entry surfaced as a generic `PackagePathNotExported` instead of the specific error — despite the comment right below claiming "Return or throw the last fallback resolution null return or error". This fixes the off-by-one (`i + 1 == targets.len()`) so the last entry's error now propagates, matching the documented intent and Node's `lastException` behavior for arrays. One deliberate exemption: `ResolveError::NotFound` still falls through. It only arises from re-resolving a bare `imports` target (e.g. `\"#a\": [{\"import\": [\"#b/import.js\"]}]`) through the module system, and enhanced-resolve treats an unresolvable candidate there as a soft failure, not a hard error — the ported "Direct and conditional mapping #4" test pins that behavior. Node would actually throw immediately on any non-`ERR_INVALID_PACKAGE_TARGET` error inside the array loop, which is stricter than enhanced-resolve; the exemption keeps us compatible with the latter. Adds two imports-field tests: an invalid target in the **last** array entry now errors (previously `Ok(None)`), and an invalid target in a **non-last** entry still falls through to the next entry. Split out of #1263.
Behavior-preserving cleanup pass across the crate (+74/−145). Verified with clippy (all features/targets),
cargo test+--all-features, s390x check, docs with-D warnings, Node tests, and the Yarn PnP fixture tests.Dead code
package_target_resolve: thei == targets.len()branch could never execute (icomes fromenumerate()so it maxes out atlen − 1), meaning errors from array entries always fall through to the next entry. Removed the branch and corrected the comment to describe the actual behavior. If the original intent was Node'slastExceptionsemantics (propagate the last entry's error), that would bei + 1 == targets.len()— deliberately not done here to keep this PR behavior-preserving.impl BitOr for Extensionsin the dts resolver: never invoked, all unions go through.union().dts_resolve_tsconfig_paths: unused_cached_pathparameter.EnforceExtension::{is_auto,is_enabled,is_disabled}: zero callers and not#[napi]-exported.let _ = meta;in themetadatatest.Redundant work
fallbackaliases are now compiled once at construction intoResolverImpl.fallback(mirroringalias) instead ofcompile_aliasre-running on every failed resolution;load_alias_by_optionsis deleted.Cache::get_tsconfigno longer deep-clones theTsConfigon the non-root (extends) path, where the clone was immediately dropped. The clone only ever mattered for the root branch becausebuild()consumesself.Simplifications
dts_resolve_as_directoryis factored intodts_package_entry, and the nestedif letcollapsed into a let-chain.clone_with_options:(a && !b) || (!a && b)→ plain==comparison; its stale#[allow(clippy::unused_self)]is removed.Resolutionuses#[derive(Clone)](the manual impl was field-for-field identical), the two identical#[cold]error constructors inSpecifier::parseare merged,require_hashusesok_or_elseinstead ofmap_or_else(|| Err(..), Ok), plus a redundant.as_ref()onfile_name()and aSome(x).as_deref().unwrap()dance are gone.TsConfig::rootfixed: template-variable substitution is driven byshould_buildnow, notroot.Noticed but intentionally not changed (behavior changes, separate discussion)
\0#path inSpecifier::parse_query_fragmentrebuilds the string withs.push(b as char)over raw bytes, which garbles multi-byte UTF-8 on that rare branch.extend_tsconfigskips thewith_extended_filecircular-extend guard thatload_tsconfigapplies.