Compare commits

...

1 Commits

Author SHA1 Message Date
Dylan Conway
47a0479bbf prefer module in exports 2023-07-31 17:31:16 -07:00
3 changed files with 97 additions and 0 deletions

View File

@@ -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", .{});
}

View File

@@ -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);

View File

@@ -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",
},
});
});