diff --git a/fixtures/pnpm/package.json b/fixtures/pnpm/package.json index b763d74d..12fd900b 100644 --- a/fixtures/pnpm/package.json +++ b/fixtures/pnpm/package.json @@ -6,6 +6,8 @@ "axios": "1.6.2", "ipaddr.js": "2.2.0", "postcss": "8.4.33", - "styled-components": "6.1.1" + "styled-components": "6.1.1", + "mathjs": "13.2.0", + "decimal.js": "10.4.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ee5896df..6cd02948 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,9 +32,15 @@ importers: axios: specifier: 1.6.2 version: 1.6.2 + decimal.js: + specifier: 10.4.3 + version: 10.4.3 ipaddr.js: specifier: 2.2.0 version: 2.2.0 + mathjs: + specifier: 13.2.0 + version: 13.2.0 postcss: specifier: 8.4.33 version: 8.4.33 @@ -67,6 +73,10 @@ importers: packages: + '@babel/runtime@7.25.7': + resolution: {integrity: sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==} + engines: {node: '>=6.9.0'} + '@emnapi/core@1.2.0': resolution: {integrity: sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==} @@ -768,6 +778,9 @@ packages: common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + complex.js@2.3.0: + resolution: {integrity: sha512-wWHzifVdUPbPBhh+ObvpVGIzrAQjTvmnnEJKBfLW5YbyAB6OXQ0r+Q92fByMIrSSlxUuCujqxriJSR6R/kVxPA==} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -809,6 +822,9 @@ packages: supports-color: optional: true + decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -846,6 +862,9 @@ packages: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} + escape-latex@1.2.0: + resolution: {integrity: sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==} + escape-string-regexp@2.0.0: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} @@ -908,6 +927,9 @@ packages: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fs-minipass@2.1.0: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} @@ -1020,6 +1042,9 @@ packages: resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} engines: {node: '>=18'} + javascript-natural-sort@0.7.1: + resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} + js-string-escape@1.0.1: resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==} engines: {node: '>= 0.8'} @@ -1057,6 +1082,11 @@ packages: resolution: {integrity: sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + mathjs@13.2.0: + resolution: {integrity: sha512-P5PZoiUX2Tkghkv3tsSqlK0B9My/ErKapv1j6wdxd0MOrYQ30cnGE4LH/kzYB2gA5rN46Njqc4cFgJjaxgijoQ==} + engines: {node: '>= 18'} + hasBin: true + md5-hex@3.0.1: resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==} engines: {node: '>=8'} @@ -1225,6 +1255,9 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -1265,6 +1298,9 @@ packages: scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + seedrandom@3.0.5: + resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -1359,6 +1395,9 @@ packages: resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} engines: {node: '>=4'} + tiny-emitter@2.1.0: + resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -1387,6 +1426,10 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} + typed-function@4.2.1: + resolution: {integrity: sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==} + engines: {node: '>= 18'} + typescript@5.6.2: resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} engines: {node: '>=14.17'} @@ -1457,6 +1500,10 @@ packages: snapshots: + '@babel/runtime@7.25.7': + dependencies: + regenerator-runtime: 0.14.1 + '@emnapi/core@1.2.0': dependencies: '@emnapi/wasi-threads': 1.0.1 @@ -2142,6 +2189,8 @@ snapshots: common-path-prefix@3.0.0: {} + complex.js@2.3.0: {} + concat-map@0.0.1: {} concordance@5.0.4: @@ -2181,6 +2230,8 @@ snapshots: dependencies: ms: 2.1.2 + decimal.js@10.4.3: {} + delayed-stream@1.0.0: {} delegates@1.0.0: {} @@ -2202,6 +2253,8 @@ snapshots: escalade@3.1.2: {} + escape-latex@1.2.0: {} + escape-string-regexp@2.0.0: {} escape-string-regexp@5.0.0: {} @@ -2252,6 +2305,8 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 + fraction.js@4.3.7: {} + fs-minipass@2.1.0: dependencies: minipass: 3.3.6 @@ -2358,6 +2413,8 @@ snapshots: is-unicode-supported@2.0.0: {} + javascript-natural-sort@0.7.1: {} + js-string-escape@1.0.1: {} js-tokens@4.0.0: {} @@ -2389,6 +2446,18 @@ snapshots: dependencies: escape-string-regexp: 5.0.0 + mathjs@13.2.0: + dependencies: + '@babel/runtime': 7.25.7 + complex.js: 2.3.0 + decimal.js: 10.4.3 + escape-latex: 1.2.0 + fraction.js: 4.3.7 + javascript-natural-sort: 0.7.1 + seedrandom: 3.0.5 + tiny-emitter: 2.1.0 + typed-function: 4.2.1 + md5-hex@3.0.1: dependencies: blueimp-md5: 2.19.0 @@ -2533,6 +2602,8 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + regenerator-runtime@0.14.1: {} + require-directory@2.1.1: {} resolve-cwd@3.0.0: @@ -2565,6 +2636,8 @@ snapshots: dependencies: loose-envify: 1.4.0 + seedrandom@3.0.5: {} + semver@6.3.1: {} semver@7.6.2: {} @@ -2658,6 +2731,8 @@ snapshots: time-zone@1.0.0: {} + tiny-emitter@2.1.0: {} + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -2678,6 +2753,8 @@ snapshots: type-fest@0.21.3: {} + typed-function@4.2.1: {} + typescript@5.6.2: {} undici-types@6.19.8: {} diff --git a/src/lib.rs b/src/lib.rs index 1a0ab009..902daa87 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1050,22 +1050,23 @@ impl ResolverGeneric { let path = cached_path.path(); let Some(filename) = path.file_name() else { return Ok(None) }; let path_without_extension = path.with_extension(""); + ctx.with_fully_specified(true); for extension in extensions { let mut path_with_extension = path_without_extension.clone().into_os_string(); path_with_extension.reserve_exact(extension.len()); path_with_extension.push(extension); let cached_path = self.cache.value(Path::new(&path_with_extension)); - // Bail if path is module directory such as `ipaddr.js` - if cached_path.is_dir(&self.cache.fs, ctx) { - ctx.with_fully_specified(false); - return Ok(None); - } if let Some(path) = self.load_alias_or_file(&cached_path, ctx)? { ctx.with_fully_specified(false); return Ok(Some(path)); } } + // Bail if path is module directory such as `ipaddr.js` + if !cached_path.is_file(&self.cache.fs, ctx) { + ctx.with_fully_specified(false); + return Ok(None); + } // Create a meaningful error message. let dir = path.parent().unwrap().to_path_buf(); let filename_without_extension = Path::new(filename).with_extension(""); diff --git a/tests/resolve_test.rs b/tests/resolve_test.rs index 63af428f..19772b60 100644 --- a/tests/resolve_test.rs +++ b/tests/resolve_test.rs @@ -130,3 +130,57 @@ fn ipaddr_js() { assert_eq!(resolution, Ok(module_path.clone())); } } + +#[test] +fn decimal_js() { + let dir = dir(); + let path = dir.join("fixtures/pnpm"); + let module_path = + dir.join("node_modules/.pnpm/decimal.js@10.4.3/node_modules/decimal.js/decimal.mjs"); + + let resolvers = [ + // with `extension_alias` + Resolver::new(ResolveOptions { + extension_alias: vec![(".js".into(), vec![".js".into(), ".ts".into(), ".tsx".into()])], + condition_names: vec!["import".into()], + ..ResolveOptions::default() + }), + // default + Resolver::new(ResolveOptions { + condition_names: vec!["import".into()], + ..ResolveOptions::default() + }), + ]; + + for resolver in resolvers { + let resolution = resolver.resolve(&path, "decimal.js").map(|r| r.full_path()); + assert_eq!(resolution, Ok(module_path.clone())); + } +} + +#[test] +fn decimal_js_from_mathjs() { + let dir = dir(); + let path = dir.join("node_modules/.pnpm/mathjs@13.2.0/node_modules/mathjs/lib/esm"); + let module_path = + dir.join("node_modules/.pnpm/decimal.js@10.4.3/node_modules/decimal.js/decimal.mjs"); + + let resolvers = [ + // with `extension_alias` + Resolver::new(ResolveOptions { + extension_alias: vec![(".js".into(), vec![".js".into(), ".ts".into(), ".tsx".into()])], + condition_names: vec!["import".into()], + ..ResolveOptions::default() + }), + // default + Resolver::new(ResolveOptions { + condition_names: vec!["import".into()], + ..ResolveOptions::default() + }), + ]; + + for resolver in resolvers { + let resolution = resolver.resolve(&path, "decimal.js").map(|r| r.full_path()); + assert_eq!(resolution, Ok(module_path.clone())); + } +}