diff options
-rw-r--r-- | src/resolver/package_json.zig | 21 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 3 | ||||
-rw-r--r-- | test/bundler/esbuild/default.test.ts | 73 |
3 files changed, 97 insertions, 0 deletions
diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig index 75e6a7c98..902829d3a 100644 --- a/src/resolver/package_json.zig +++ b/src/resolver/package_json.zig @@ -1248,6 +1248,7 @@ pub const ESModule = struct { conditions: ConditionsMap, allocator: std.mem.Allocator, module_type: *options.ModuleType = undefined, + prefer_module_field_in_exports: bool, pub const Resolution = struct { status: Status = Status.Undefined, @@ -1767,6 +1768,8 @@ pub const ESModule = struct { var did_find_map_entry = false; var last_map_entry_i: usize = 0; + var module_resolution: ?Resolution = null; + const slice = object.list.slice(); const keys = slice.items(.key); for (keys, 0..) |key, i| { @@ -1792,6 +1795,19 @@ pub const ESModule = struct { r.module_type.* = .cjs; } + if (strings.eqlComptime(key, "module")) { + if (r.prefer_module_field_in_exports) { + r.module_type.* = .esm; + return result; + } + + // Node will not choose the "module" field in "exports". If it's not preferred, bun will + // use the "module" field if no other conditions match. This behavior is similar to + // the top-level "module" field. + module_resolution = result; + continue; + } + return result; } @@ -1800,6 +1816,11 @@ pub const ESModule = struct { } } + if (module_resolution) |result| { + r.module_type.* = .esm; + return result; + } + if (r.debug_logs) |log| { log.addNoteFmt("No keys matched", .{}); } diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 49ce9ec11..b7044a625 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -1610,6 +1610,7 @@ pub const Resolver = struct { .allocator = r.allocator, .debug_logs = if (r.debug_logs) |*debug| debug else null, .module_type = &module_type, + .prefer_module_field_in_exports = r.prefer_module_field, }; // Resolve against the path "/", then join it with the absolute @@ -1875,6 +1876,7 @@ pub const Resolver = struct { debug else null, + .prefer_module_field_in_exports = r.prefer_module_field, }; // Resolve against the path "/", then join it with the absolute @@ -2853,6 +2855,7 @@ pub const Resolver = struct { .allocator = r.allocator, .debug_logs = if (r.debug_logs) |*debug| debug else null, .module_type = &module_type, + .prefer_module_field_in_exports = r.prefer_module_field, }; const esm_resolution = esmodule.resolveImports(import_path, imports_map.root); diff --git a/test/bundler/esbuild/default.test.ts b/test/bundler/esbuild/default.test.ts index ac820848a..0d17312ed 100644 --- a/test/bundler/esbuild/default.test.ts +++ b/test/bundler/esbuild/default.test.ts @@ -6836,4 +6836,77 @@ describe("bundler", () => { stdout: "5 9 2 7", }, }); + const fooNodeModule = { + "/node_modules/foo/package.json": ` + { + "name": "foo", + "version": "2.0.0", + "exports": { + ".": { + "module": "./import.js", + "require": "./require.js", + "import": "./import.js" + } + } + } + `, + "/node_modules/foo/import.js": ` + export const foo = 'import'; + `, + "/node_modules/foo/require.js": ` + export const foo = 'require'; + `, + }; + itBundled("default/ExportFieldWithModuleRuntimeImport", { + files: { + "/entry.js": ` + import { foo } from 'foo'; + console.log(foo); + `, + ...fooNodeModule, + }, + bundling: false, + run: { + stdout: "import", + }, + }); + itBundled("default/ExportsFieldWithModuleBundleImport", { + files: { + "/entry.js": ` + import { foo } from 'foo'; + console.log(foo); + `, + ...fooNodeModule, + }, + bundling: true, + run: { + stdout: "import", + }, + }); + itBundled("default/ExportsFieldWithModuleRuntimeRequire", { + files: { + "/entry.js": ` + const { foo } = require('foo'); + console.log(foo); + `, + ...fooNodeModule, + }, + bundling: false, + run: { + stdout: "require", + }, + }); + itBundled("default/ExportsFieldWithModuleBundleRequire", { + files: { + "/entry.js": ` + const { foo } = require('foo'); + console.log(foo); + `, + ...fooNodeModule, + }, + bundling: true, + run: { + stdout: "import", + }, + }); }); |