diff options
author | 2021-09-22 04:08:40 -0700 | |
---|---|---|
committer | 2021-09-22 04:08:40 -0700 | |
commit | 9f7d05bab4f76ee1e51204bd3479c65ab3b9d824 (patch) | |
tree | c186e76fcea40dc7834093afc3dc8d7e1d004bea /src | |
parent | 53c0a4b5685908abc2f8ebdfa511925edb6b4110 (diff) | |
download | bun-9f7d05bab4f76ee1e51204bd3479c65ab3b9d824.tar.gz bun-9f7d05bab4f76ee1e51204bd3479c65ab3b9d824.tar.zst bun-9f7d05bab4f76ee1e51204bd3479c65ab3b9d824.zip |
Print how many lines of code was parsed in `bun bun`
Diffstat (limited to 'src')
-rw-r--r-- | src/bundler.zig | 16 | ||||
-rw-r--r-- | src/cli/bun_command.zig | 31 | ||||
-rw-r--r-- | src/js_parser/js_parser.zig | 31 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 1 |
4 files changed, 62 insertions, 17 deletions
diff --git a/src/bundler.zig b/src/bundler.zig index d832c01fe..5a947b656 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -431,6 +431,8 @@ pub fn NewBundler(cache_files: bool) type { while (generator.queue.next()) |item| { try generator.processFile(worker, item); } + + generator.estimated_input_lines_of_code = worker.data.estimated_input_lines_of_code; return; } @@ -475,6 +477,7 @@ pub fn NewBundler(cache_files: bool) type { shared_buffer: MutableString = undefined, scan_pass_result: js_parser.ScanPassResult = undefined, log: *logger.Log, + estimated_input_lines_of_code: usize = 0, pub fn deinit(this: *WorkerData, allocator: *std.mem.Allocator) void { this.shared_buffer.deinit(); @@ -530,6 +533,7 @@ pub fn NewBundler(cache_files: bool) type { this.data = this.generator.allocator.create(WorkerData) catch unreachable; this.data.* = WorkerData{ .log = this.generator.allocator.create(logger.Log) catch unreachable, + .estimated_input_lines_of_code = 0, }; this.data.log.* = logger.Log.init(this.generator.allocator); this.data.shared_buffer = try MutableString.init(this.generator.allocator, 0); @@ -539,6 +543,7 @@ pub fn NewBundler(cache_files: bool) type { { this.generator.log_lock.lock(); this.data.log.appendTo(this.generator.log) catch {}; + this.generator.estimated_input_lines_of_code += this.data.estimated_input_lines_of_code; this.generator.log_lock.unlock(); } @@ -576,6 +581,7 @@ pub fn NewBundler(cache_files: bool) type { tmpfile_byte_offset: u32 = 0, code_end_byte_offset: u32 = 0, has_jsx: bool = false, + estimated_input_lines_of_code: usize = 0, work_waiter: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(0), list_lock: Lock = Lock.init(), @@ -666,6 +672,7 @@ pub fn NewBundler(cache_files: bool) type { framework_config: ?Api.LoadedFramework, route_config: ?Api.LoadedRouteConfig, destination: [*:0]const u8, + estimated_input_lines_of_code: *usize, ) !?Api.JavascriptBundleContainer { var tmpdir: std.fs.Dir = try bundler.fs.fs.openTmpDir(); var tmpname_buf: [64]u8 = undefined; @@ -694,6 +701,7 @@ pub fn NewBundler(cache_files: bool) type { .header_string_buffer = try MutableString.init(allocator, "dist/index.js".len), .allocator = allocator, .queue = queue, + .estimated_input_lines_of_code = 0, // .resolve_queue = queue, .bundler = bundler, .tmpfile = tmpfile, @@ -834,6 +842,7 @@ pub fn NewBundler(cache_files: bool) type { try this.pool.start(this); try this.pool.wait(this); + estimated_input_lines_of_code.* = generator.estimated_input_lines_of_code; // if (comptime !isRelease) { // this.queue.checkDuplicatesSlow(); @@ -1023,7 +1032,6 @@ pub fn NewBundler(cache_files: bool) type { 0000010 | 0000100 | 0000001 | 0001000 | 0000040 | 0000004 | 0000002 | 0000400 | 0000200 | 0000020, ); try std.os.renameatZ(tmpdir.fd, tmpname, top_dir.fd, destination); - // Print any errors at the end // try this.log.print(Output.errorWriter()); return javascript_bundle_container; @@ -1275,6 +1283,9 @@ pub fn NewBundler(cache_files: bool) type { }; }; + var approximate_newline_count: usize = 0; + defer worker.data.estimated_input_lines_of_code += approximate_newline_count; + // Handle empty files // We can't just ignore them. Sometimes code will try to import it. Often because of TypeScript types. // So we just say it's an empty object. Empty object mimicks what "browser": false does as well. @@ -1313,6 +1324,7 @@ pub fn NewBundler(cache_files: bool) type { log, &source, )) orelse return; + approximate_newline_count = ast.approximate_newline_count; if (ast.import_records.len > 0) { for (ast.import_records) |*import_record, record_id| { @@ -1553,7 +1565,6 @@ pub fn NewBundler(cache_files: bool) type { // It should only have one part. ast.parts = ast.parts[ast.parts.len - 1 ..]; - const write_result = try js_printer.printCommonJSThreaded( @TypeOf(writer), @@ -1631,6 +1642,7 @@ pub fn NewBundler(cache_files: bool) type { log, &source, ); + worker.data.estimated_input_lines_of_code += scan_pass_result.approximate_newline_count; { for (scan_pass_result.import_records.items) |*import_record, i| { diff --git a/src/cli/bun_command.zig b/src/cli/bun_command.zig index 89a7d2360..66bd2ccee 100644 --- a/src/cli/bun_command.zig +++ b/src/cli/bun_command.zig @@ -26,6 +26,7 @@ const fs = @import("../fs.zig"); const Router = @import("../router.zig"); var wait_group: sync.WaitGroup = undefined; +var estimated_input_lines_of_code_: usize = undefined; const ServerBundleGeneratorThread = struct { inline fn _generate( logs: *logger.Log, @@ -51,13 +52,14 @@ const ServerBundleGeneratorThread = struct { Output.prettyErrorln("<r><red>{s}<r> loading --define or .env values for node_modules.server.bun\n", .{@errorName(err)}); return err; }; - + var estimated_input_lines_of_code: usize = 0; _ = try bundler.ServeBundler.GenerateNodeModuleBundle.generate( &server_bundler, allocator_, server_conf, route_conf_, _filepath, + &estimated_input_lines_of_code, ); std.mem.doNotOptimizeAway(&server_bundler); } @@ -95,6 +97,7 @@ pub const BunCommand = struct { ) !void { var allocator = ctx.allocator; var log = ctx.log; + estimated_input_lines_of_code_ = 0; var this_bundler = try bundler.ServeBundler.init(allocator, log, ctx.args, null, null); this_bundler.configureLinker(); @@ -164,6 +167,7 @@ pub const BunCommand = struct { } { + // Always generate the client-only bundle // we can revisit this decision if people ask var node_modules_ = try bundler.ServeBundler.GenerateNodeModuleBundle.generate( @@ -172,8 +176,10 @@ pub const BunCommand = struct { loaded_framework, loaded_route_config, filepath, + &estimated_input_lines_of_code_, ); + const estimated_input_lines_of_code = estimated_input_lines_of_code_; if (server_bundler_generator_thread) |thread| { wait_group.wait(); } @@ -189,6 +195,27 @@ pub const BunCommand = struct { bundle.printSummary(); } const indent = comptime " "; + + switch (estimated_input_lines_of_code) { + 0...99999 => { + if (generated_server) { + Output.prettyln(indent ++ "<d>{d:<5} LOC parsed x2", .{estimated_input_lines_of_code}); + } else { + Output.prettyln(indent ++ "<d>{d:<5} LOC parsed", .{estimated_input_lines_of_code}); + } + }, + else => { + const formatted_loc: f32 = @floatCast(f32, @intToFloat(f128, estimated_input_lines_of_code) / 1000); + if (generated_server) { + Output.prettyln(indent ++ "<d>{d:<5.2}k LOC parsed x2", .{formatted_loc}); + } else { + Output.prettyln(indent ++ "<d>{d:<5.2}k LOC parsed", .{ + formatted_loc, + }); + } + }, + } + Output.prettyln(indent ++ "<d>{d:6}ms elapsed", .{@intCast(u32, elapsed)}); if (generated_server) { @@ -197,6 +224,8 @@ pub const BunCommand = struct { Output.prettyln(indent ++ "<r>Saved to ./{s}", .{filepath}); } + Output.flush(); + try log.printForLogLevel(Output.errorWriter()); } } else { diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index a32a077ac..043b11b37 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -1730,6 +1730,7 @@ pub const ScanPassResult = struct { named_imports: js_ast.Ast.NamedImports, used_symbols: ParsePassSymbolUsageMap, import_records_to_keep: List(u32), + approximate_newline_count: usize = 0, pub fn init(allocator: *std.mem.Allocator) ScanPassResult { return .{ @@ -1737,6 +1738,7 @@ pub const ScanPassResult = struct { .named_imports = js_ast.Ast.NamedImports.init(allocator), .used_symbols = ParsePassSymbolUsageMap.init(allocator), .import_records_to_keep = List(u32).init(allocator), + .approximate_newline_count = 0, }; } @@ -1744,6 +1746,7 @@ pub const ScanPassResult = struct { scan_pass.named_imports.clearRetainingCapacity(); scan_pass.import_records.shrinkRetainingCapacity(0); scan_pass.used_symbols.clearRetainingCapacity(); + scan_pass.approximate_newline_count = 0; } }; @@ -1871,6 +1874,8 @@ pub const Parser = struct { p.options.jsx.classic_import_source, ); } + + scan_pass.approximate_newline_count = p.lexer.approximate_newline_count; } pub fn parse(self: *Parser) !js_ast.Result { @@ -3919,7 +3924,6 @@ pub fn NewParser( fn convertExprToBindingAndInitializer(p: *P, _expr: *ExprNodeIndex, invalid_log: *LocList, is_spread: bool) ExprBindingTuple { var initializer: ?ExprNodeIndex = null; var expr = _expr; - var override: ?ExprNodeIndex = null; // zig syntax is sometimes painful switch (expr.*.data) { .e_binary => |bin| { @@ -4234,7 +4238,7 @@ pub fn NewParser( try p.lexer.next(); } if (args.items.len > 0) { - func.args = args.toOwnedSlice(); + func.args = args.items; } // Reserve the special name "arguments" in this scope. This ensures that it @@ -4293,7 +4297,7 @@ pub fn NewParser( try decorators.append(try p.parseExprWithFlags(.new, Expr.EFlags.ts_decorator)); } - return decorators.toOwnedSlice(); + return decorators.items; } pub const TypeScript = struct { @@ -5708,10 +5712,10 @@ pub fn NewParser( }, } } - try cases.append(js_ast.Case{ .value = value, .body = body.toOwnedSlice(), .loc = logger.Loc.Empty }); + try cases.append(js_ast.Case{ .value = value, .body = body.items, .loc = logger.Loc.Empty }); } try p.lexer.expect(.t_close_brace); - return p.s(S.Switch{ .test_ = test_, .body_loc = body_loc, .cases = cases.toOwnedSlice() }, loc); + return p.s(S.Switch{ .test_ = test_, .body_loc = body_loc, .cases = cases.items }, loc); }, .t_try => { try p.lexer.next(); @@ -6361,7 +6365,7 @@ pub fn NewParser( for (local.decls) |decl| { try extractDeclsForBinding(decl.binding, &_decls); } - decls = _decls.toOwnedSlice(); + decls = _decls.items; }, else => {}, } @@ -6548,7 +6552,7 @@ pub fn NewParser( } return p.s( - S.Namespace{ .name = name, .arg = arg_ref orelse Ref.None, .stmts = stmts.toOwnedSlice(), .is_export = opts.is_export }, + S.Namespace{ .name = name, .arg = arg_ref orelse Ref.None, .stmts = stmts.items, .is_export = opts.is_export }, loc, ); } @@ -6724,7 +6728,7 @@ pub fn NewParser( } try p.lexer.expect(.t_close_brace); - return ImportClause{ .items = items.toOwnedSlice(), .is_single_line = is_single_line }; + return ImportClause{ .items = items.items, .is_single_line = is_single_line }; } fn forbidInitializers(p: *P, decls: []G.Decl, loop_type: string, is_var: bool) !void { @@ -6880,7 +6884,7 @@ pub fn NewParser( } try p.lexer.expect(.t_close_bracket); return p.b(B.Array{ - .items = items.toOwnedSlice(), + .items = items.items, .has_spread = has_spread, .is_single_line = is_single_line, }, loc); @@ -6926,7 +6930,7 @@ pub fn NewParser( try p.lexer.expect(.t_close_brace); return p.b(B.Object{ - .properties = properties.toOwnedSlice(), + .properties = properties.items, .is_single_line = is_single_line, }, loc); }, @@ -13956,7 +13960,7 @@ pub fn NewParser( // Eat the comma token try p.lexer.next(); } - var items = if (items_list.capacity > 0) items_list.toOwnedSlice() else &([_]Expr{}); + var items = items_list.items; // The parenthetical construct must end with a close parenthesis try p.lexer.expect(.t_close_paren); @@ -13993,10 +13997,11 @@ pub fn NewParser( else => {}, } - const tuple = p.convertExprToBindingAndInitializer(&items[i], &invalidLog, is_spread); + var item = items[i]; + const tuple = p.convertExprToBindingAndInitializer(&item, &invalidLog, is_spread); // double allocations args.append(G.Arg{ - .binding = tuple.binding orelse Binding{ .data = Prefill.Data.BMissing, .loc = items[i].loc }, + .binding = tuple.binding orelse Binding{ .data = Prefill.Data.BMissing, .loc = item.loc }, .default = tuple.expr, }) catch unreachable; } diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 31c1ac1fc..72a3febf7 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -1201,7 +1201,6 @@ pub fn NewResolver(cache_files: bool) type { // paths. We also want to avoid any "%" characters in the absolute // directory path accidentally being interpreted as URL escapes. var esm_resolution = esmodule.resolve("/", esm.subpath, exports_map.root); - defer Output.debug("ESM Resolution Status {s}: {s}\n", .{ abs_package_path, esm_resolution.status }); if ((esm_resolution.status == .Inexact or esm_resolution.status == .Exact) and strings.startsWith(esm_resolution.path, "/")) { const abs_esm_path: string = brk: { |