aboutsummaryrefslogtreecommitdiff
path: root/src/bundler/bundle_v2.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/bundler/bundle_v2.zig')
-rw-r--r--src/bundler/bundle_v2.zig84
1 files changed, 75 insertions, 9 deletions
diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig
index 6a1cf486c..0a5b238b0 100644
--- a/src/bundler/bundle_v2.zig
+++ b/src/bundler/bundle_v2.zig
@@ -946,7 +946,9 @@ const ParseTask = struct {
opts.features.top_level_await = true;
opts.features.jsx_optimization_inline = platform.isBun() and (bundler.options.jsx_optimization_inline orelse !task.jsx.development);
opts.features.auto_import_jsx = task.jsx.parse and bundler.options.auto_import_jsx;
- opts.features.trim_unused_imports = bundler.options.trim_unused_imports orelse loader.isTypeScript();
+ opts.features.trim_unused_imports = loader.isTypeScript() or (bundler.options.trim_unused_imports orelse false);
+ opts.features.inlining = true;
+
opts.tree_shaking = task.tree_shaking;
opts.module_type = task.module_type;
task.jsx.parse = loader.isJSX();
@@ -1445,6 +1447,8 @@ pub const Graph = struct {
use_directive_entry_points: UseDirective.List = .{},
+ const_values: std.HashMapUnmanaged(Ref, Expr, Ref.HashCtx, 80) = .{},
+
pub const InputFile = struct {
source: Logger.Source,
loader: options.Loader = options.Loader.file,
@@ -1543,6 +1547,8 @@ const LinkerGraph = struct {
has_client_components: bool = false,
has_server_components: bool = false,
+ const_values: std.HashMapUnmanaged(Ref, Expr, Ref.HashCtx, 80) = .{},
+
pub fn init(allocator: std.mem.Allocator, file_count: usize) !LinkerGraph {
return LinkerGraph{
.allocator = allocator,
@@ -1910,6 +1916,26 @@ const LinkerGraph = struct {
this.symbols = js_ast.Symbol.Map.initList(symbols);
}
+ {
+ var const_values = this.const_values;
+ var count: usize = 0;
+
+ for (this.ast.items(.const_values)) |const_value| {
+ count += const_value.count();
+ }
+
+ if (count > 0) {
+ try const_values.ensureTotalCapacity(this.allocator, @truncate(u32, count));
+ for (this.ast.items(.const_values)) |const_value| {
+ for (const_value.keys(), const_value.values()) |key, value| {
+ const_values.putAssumeCapacityNoClobber(key, value);
+ }
+ }
+ }
+
+ this.const_values = const_values;
+ }
+
var in_resolved_exports: []ResolvedExports = this.meta.items(.resolved_exports);
var src_resolved_exports: []js_ast.Ast.NamedExports = this.ast.items(.named_exports);
for (src_resolved_exports, in_resolved_exports, 0..) |src, *dest, source_index| {
@@ -2363,7 +2389,7 @@ const LinkerContext = struct {
const part_index = @truncate(u32, part_index_);
const is_part_in_this_chunk = is_file_in_chunk and part.is_live;
for (part.import_record_indices.slice()) |record_id| {
- const record = &records[record_id];
+ const record: *const ImportRecord = &records[record_id];
if (record.source_index.isValid() and (record.kind == .stmt or is_part_in_this_chunk)) {
if (v.c.isExternalDynamicImport(record, source_index)) {
// Don't follow import() dependencies
@@ -3431,7 +3457,6 @@ const LinkerContext = struct {
const loc = Logger.Loc.Empty;
// todo: investigate if preallocating this array is faster
var ns_export_dependencies = std.ArrayList(js_ast.Dependency).initCapacity(allocator_, re_exports_count) catch unreachable;
-
for (export_aliases) |alias| {
var export_ = resolved_exports.getPtr(alias).?;
@@ -3719,14 +3744,52 @@ const LinkerContext = struct {
var parts_slice: []js_ast.Part = parts.slice();
var named_imports: js_ast.Ast.NamedImports = c.graph.ast.items(.named_imports)[id];
defer c.graph.ast.items(.named_imports)[id] = named_imports;
- for (parts_slice, 0..) |*part, part_index| {
+ outer: for (parts_slice, 0..) |*part, part_index| {
// TODO: inline const TypeScript enum here
// TODO: inline function calls here
- // note: if we crash on append, it is due to threadlocal heaps in mimalloc
- const symbol_uses = part.symbol_uses.keys();
+ // Inline cross-module constants
+ if (c.graph.const_values.count() > 0) {
+ // First, find any symbol usage that points to a constant value.
+ // This will be pretty rare.
+ const first_constant_i: ?usize = brk: {
+ for (part.symbol_uses.keys(), 0..) |ref, j| {
+ if (c.graph.const_values.contains(ref)) {
+ break :brk j;
+ }
+ }
+
+ break :brk null;
+ };
+ if (first_constant_i) |j| {
+ var end_i: usize = 0;
+ // symbol_uses is an array
+ var keys = part.symbol_uses.keys()[j..];
+ var values = part.symbol_uses.values()[j..];
+ for (keys, values) |ref, val| {
+ if (c.graph.const_values.contains(ref)) {
+ continue;
+ }
+
+ keys[end_i] = ref;
+ values[end_i] = val;
+ end_i += 1;
+ }
+ part.symbol_uses.entries.len = end_i + j;
+
+ if (part.symbol_uses.entries.len == 0 and part.can_be_removed_if_unused) {
+ part.tag = .dead_due_to_inlining;
+ part.dependencies.len = 0;
+ continue :outer;
+ }
+
+ part.symbol_uses.reIndex(allocator_) catch unreachable;
+ }
+ }
+
+ var symbol_uses = part.symbol_uses.keys();
// Now that we know this, we can determine cross-part dependencies
for (symbol_uses, 0..) |ref, j| {
@@ -3734,8 +3797,6 @@ const LinkerContext = struct {
std.debug.assert(part.symbol_uses.values()[j].count_estimate > 0);
}
- // TODO: inline const values from an import
-
const other_parts = c.topLevelSymbolsToParts(id, ref);
for (other_parts) |other_part_index| {
@@ -4566,6 +4627,7 @@ const LinkerContext = struct {
.allocator = allocator,
.require_ref = runtimeRequireRef,
.minify_whitespace = c.options.minify_whitespace,
+ .const_values = c.graph.const_values,
};
var cross_chunk_import_records = ImportRecord.List.initCapacity(allocator, chunk.cross_chunk_imports.len) catch unreachable;
@@ -5190,6 +5252,7 @@ const LinkerContext = struct {
.require_or_import_meta_for_source_callback = js_printer.RequireOrImportMeta.Callback.init(LinkerContext, requireOrImportMetaForSource, c),
.minify_whitespace = c.options.minify_whitespace,
+ .const_values = c.graph.const_values,
};
return .{
@@ -5787,6 +5850,7 @@ const LinkerContext = struct {
stmt.loc,
);
stmt.data.s_local.is_export = false;
+
}
},
@@ -6379,6 +6443,7 @@ const LinkerContext = struct {
.commonjs_named_exports = ast.commonjs_named_exports,
.commonjs_named_exports_ref = ast.exports_ref,
+ .const_values = c.graph.const_values,
.allocator = allocator,
.to_esm_ref = toESMRef,
@@ -6692,7 +6757,8 @@ const LinkerContext = struct {
}
}
- for (parts[source_index].slice()) |part| {
+ const parts_in_file = parts[source_index].slice();
+ for (parts_in_file) |part| {
for (part.dependencies.slice()) |dependency| {
if (dependency.source_index.get() != source_index) {
if (imports_a_boundary and