Skip to content

Commit

Permalink
Merge branch 'main' into dylan/upgrade-webkit
Browse files Browse the repository at this point in the history
  • Loading branch information
dylan-conway authored Jul 10, 2024
2 parents 377f339 + 73ef93f commit 986141a
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/analytics/analytics_thread.zig
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub const Features = struct {
pub var WebSocket: usize = 0;
pub var no_avx: usize = 0;
pub var no_avx2: usize = 0;
pub var binlinks: usize = 0;
pub var builtin_modules = std.enums.EnumSet(bun.JSC.HardcodedModule).initEmpty();

pub fn formatter() Formatter {
Expand Down
5 changes: 4 additions & 1 deletion src/bun.js/api/server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,7 @@ fn NewFlags(comptime debug_mode: bool) type {
has_marked_pending: bool = false,
has_abort_handler: bool = false,
has_sendfile_ctx: bool = false,
has_pending_read: bool = false,
has_called_error_handler: bool = false,
needs_content_length: bool = false,
needs_content_range: bool = false,
Expand Down Expand Up @@ -1826,7 +1827,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
}

pub fn isDeadRequest(this: *RequestContext) bool {
if (this.pending_promises_for_abort > 0) return false;
if (this.pending_promises_for_abort > 0 or this.flags.has_pending_read) return false;

if (this.promise != null) {
return false;
Expand Down Expand Up @@ -2335,10 +2336,12 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
}

this.setAbortHandler();
this.flags.has_pending_read = true;
this.blob.Blob.doReadFileInternal(*RequestContext, this, onReadFile, this.server.globalThis);
}

pub fn onReadFile(this: *RequestContext, result: Blob.ReadFile.ResultType) void {
this.flags.has_pending_read = false;
if (this.flags.aborted or this.resp == null) {
this.finalizeForAbort();
return;
Expand Down
2 changes: 1 addition & 1 deletion src/bun.js/test/jest.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1551,7 +1551,7 @@ pub const TestRunnerTask = struct {
},
.pending => @panic("Unexpected pending test"),
}
describe.onTestComplete(globalThis, test_id, result == .skip);
describe.onTestComplete(globalThis, test_id, result == .skip or (!Jest.runner.?.test_options.run_todo and result == .todo));
Jest.runner.?.runNextTest();
}

Expand Down
8 changes: 4 additions & 4 deletions src/http.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2101,8 +2101,8 @@ pub const AsyncHTTP = struct {
assert(active_requests > 0);
}

if (AsyncHTTP.active_requests_count.load(.monotonic) < AsyncHTTP.max_simultaneous_requests.load(.monotonic)) {
http_thread.drainEvents();
if (!http_thread.queued_tasks.isEmpty() and AsyncHTTP.active_requests_count.load(.monotonic) < AsyncHTTP.max_simultaneous_requests.load(.monotonic)) {
http_thread.loop.loop.wakeup();
}
}

Expand Down Expand Up @@ -2314,7 +2314,7 @@ fn start_(this: *HTTPClient, comptime is_ssl: bool) void {

// Aborted before connecting
if (this.signals.get(.aborted)) {
this.fail(error.Aborted);
this.fail(error.AbortedBeforeConnecting);
return;
}

Expand Down Expand Up @@ -3132,7 +3132,7 @@ pub const HTTPClientResult = struct {
}

pub fn isAbort(this: *const HTTPClientResult) bool {
return if (this.fail) |e| e == error.Aborted else false;
return if (this.fail) |e| (e == error.Aborted or e == error.AbortedBeforeConnecting) else false;
}

pub const Callback = struct {
Expand Down
4 changes: 2 additions & 2 deletions src/ini.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,7 @@ pub fn loadNpmrc(
source,
iter.config.properties.at(iter.prop_idx - 1).key.?.loc,
allocator,
"The follwing .npmrc registry option was not applied:\n\n <b>{s}<r>\n\nBecause we currently don't support the <b>{s}<r> option.",
"The following .npmrc registry option was not applied:\n\n <b>{s}<r>\n\nBecause we currently don't support the <b>{s}<r> option.",
.{
conf_item,
@tagName(conf_item.optname),
Expand Down Expand Up @@ -1130,7 +1130,7 @@ pub fn loadNpmrc(
source,
iter.config.properties.at(iter.prop_idx - 1).key.?.loc,
allocator,
"The follwing .npmrc registry option was not applied:\n\n <b>{s}<r>\n\nBecause we couldn't find the registry: <b>{s}<r>.",
"The following .npmrc registry option was not applied:\n\n <b>{s}<r>\n\nBecause we couldn't find the registry: <b>{s}<r>.",
.{
conf_item,
conf_item.registry_url,
Expand Down
6 changes: 4 additions & 2 deletions src/install/bin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ pub const Bin = extern struct {
return;
}

bun.Analytics.Features.binlinks += 1;

if (comptime Environment.isWindows)
this.createWindowsShim(abs_target, abs_dest, global)
else
Expand Down Expand Up @@ -399,7 +401,7 @@ pub const Bin = extern struct {
}
}

pub fn createWindowsShim(this: *Linker, abs_target: [:0]const u8, abs_dest: [:0]const u8, global: bool) void {
fn createWindowsShim(this: *Linker, abs_target: [:0]const u8, abs_dest: [:0]const u8, global: bool) void {
const WinBinLinkingShim = @import("./windows-shim/BinLinkingShim.zig");

var shim_buf: [65536]u8 = undefined;
Expand Down Expand Up @@ -486,7 +488,7 @@ pub const Bin = extern struct {
};
}

pub fn createSymlink(this: *Linker, abs_target: [:0]const u8, abs_dest: [:0]const u8, global: bool) void {
fn createSymlink(this: *Linker, abs_target: [:0]const u8, abs_dest: [:0]const u8, global: bool) void {
defer {
if (this.err == null) {
_ = bun.sys.chmod(abs_target, umask | 0o777);
Expand Down
141 changes: 141 additions & 0 deletions src/install/install.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2586,6 +2586,10 @@ pub const PackageManager = struct {
progress_name_buf_dynamic: []u8 = &[_]u8{},
cpu_count: u32 = 0,

track_installed_bin: TrackInstalledBin = .{
.none = {},
},

// progress bar stuff when not stack allocated
root_progress_node: *Progress.Node = undefined,

Expand Down Expand Up @@ -2710,6 +2714,12 @@ pub const PackageManager = struct {
Global.crash();
}

const TrackInstalledBin = union(enum) {
none: void,
pending: void,
basename: []const u8,
};

// maybe rename to `PackageJSONCache` if we cache more than workspaces
pub const WorkspacePackageJSONCache = struct {
const js_ast = bun.JSAst;
Expand Down Expand Up @@ -8210,6 +8220,13 @@ pub const PackageManager = struct {
unlink,
patch,
@"patch-commit",

pub fn canGloballyInstallPackages(this: Subcommand) bool {
return switch (this) {
.install, .update, .add => true,
else => false,
};
}
};

pub fn init(ctx: Command.Context, comptime subcommand: Subcommand) !*PackageManager {
Expand Down Expand Up @@ -9739,6 +9756,14 @@ pub const PackageManager = struct {
Output.flush();
}

// When you run `bun add -g <pkg>` or `bun install -g <pkg>` and the global bin dir is not in $PATH
// We should tell the user to add it to $PATH so they don't get confused.
if (subcommand.canGloballyInstallPackages()) {
if (manager.options.global and manager.options.log_level != .silent) {
manager.track_installed_bin = .{ .pending = {} };
}
}

switch (manager.options.log_level) {
inline else => |log_level| try manager.updatePackageJSONAndInstallWithManager(ctx, log_level),
}
Expand All @@ -9750,6 +9775,122 @@ pub const PackageManager = struct {
if (manager.any_failed_to_install) {
Global.exit(1);
}

// Check if we need to print a warning like:
//
// > warn: To run "vite", add the global bin folder to $PATH:
// >
// > fish_add_path "/private/tmp/test"
//
if (subcommand.canGloballyInstallPackages()) {
if (manager.options.global) {
if (manager.options.bin_path.len > 0 and manager.track_installed_bin == .basename) {
const needs_to_print = if (bun.getenvZ("PATH")) |PATH|
// This is not perfect
//
// If you already have a different binary of the same
// name, it will not detect that case.
//
// The problem is there are too many edgecases with filesystem paths.
//
// We want to veer towards false negative than false
// positive. It would be annoying if this message
// appears unnecessarily. It's kind of okay if it doesn't appear
// when it should.
//
// If you set BUN_INSTALL_BIN to "/tmp/woo" on macOS and
// we just checked for "/tmp/woo" in $PATH, it would
// incorrectly print a warning because /tmp/ on macOS is
// aliased to /private/tmp/
//
// Another scenario is case-insensitive filesystems. If you
// have a binary called "esbuild" in /tmp/TeST and you
// install esbuild, it will not detect that case if we naively
// just checked for "esbuild" in $PATH where "$PATH" is /tmp/test
bun.which(
&package_json_cwd_buf,
PATH,
bun.fs.FileSystem.instance.top_level_dir,
manager.track_installed_bin.basename,
) == null
else
true;

if (needs_to_print) {
const MoreInstructions = struct {
shell: bun.CLI.ShellCompletions.Shell = .unknown,
folder: []const u8,

// Convert "/Users/Jarred Sumner" => "/Users/Jarred\ Sumner"
const ShellPathFormatter = struct {
folder: []const u8,

pub fn format(instructions: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
var remaining = instructions.folder;
while (bun.strings.indexOfChar(remaining, ' ')) |space| {
try writer.print(
"{}",
.{bun.fmt.fmtPath(u8, remaining[0..space], .{
.escape_backslashes = true,
.path_sep = if (Environment.isWindows) .windows else .posix,
})},
);
try writer.writeAll("\\ ");
remaining = remaining[@min(space + 1, remaining.len)..];
}

try writer.print(
"{}",
.{bun.fmt.fmtPath(u8, remaining, .{
.escape_backslashes = true,
.path_sep = if (Environment.isWindows) .windows else .posix,
})},
);
}
};

pub fn format(instructions: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
const path = ShellPathFormatter{ .folder = instructions.folder };
switch (instructions.shell) {
.unknown => {
// Unfortunately really difficult to do this in one line on PowerShell.
try writer.print("{}", .{path});
},
.bash => {
try writer.print("export PATH=\"{}:$PATH\"", .{path});
},
.zsh => {
try writer.print("export PATH=\"{}:$PATH\"", .{path});
},
.fish => {
// Regular quotes will do here.
try writer.print("fish_add_path {}", .{bun.fmt.quote(instructions.folder)});
},
.pwsh => {
try writer.print("$env:PATH += \";{}\"", .{path});
},
}
}
};

Output.prettyError("\n", .{});

Output.warn(
\\To run {}, add the global bin folder to $PATH:
\\
\\<cyan>{}<r>
\\
,
.{
bun.fmt.quote(manager.track_installed_bin.basename),
MoreInstructions{ .shell = bun.CLI.ShellCompletions.Shell.fromEnv([]const u8, bun.getenvZ("SHELL") orelse ""), .folder = manager.options.bin_path },
},
);
Output.flush();
}
}
}
}
}

fn updatePackageJSONAndInstallWithManager(
Expand Down
36 changes: 24 additions & 12 deletions src/install/lockfile.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1717,24 +1717,36 @@ pub const Printer = struct {
.extern_string_buf = this.lockfile.buffers.extern_strings.items,
};

const fmt = comptime Output.prettyFmt("<r><green>installed<r> {s}<r><d>@{}<r> with binaries:\n", enable_ansi_colors);
{
const fmt = comptime Output.prettyFmt("<r><green>installed<r> {s}<r><d>@{}<r> with binaries:\n", enable_ansi_colors);

try writer.print(
fmt,
.{
package_name,
resolved[package_id].fmt(string_buf, .posix),
},
);

while (iterator.next() catch null) |bin_name| {
try writer.print(
comptime Output.prettyFmt("<r> <d>- <r><b>{s}<r>\n", enable_ansi_colors),
fmt,
.{
bin_name,
package_name,
resolved[package_id].fmt(string_buf, .posix),
},
);
}

{
const fmt = comptime Output.prettyFmt("<r> <d>- <r><b>{s}<r>\n", enable_ansi_colors);
var manager = &bun.PackageManager.instance;

if (manager.track_installed_bin == .pending) {
if (iterator.next() catch null) |bin_name| {
manager.track_installed_bin = .{
.basename = bun.default_allocator.dupe(u8, bin_name) catch bun.outOfMemory(),
};

try writer.print(fmt, .{bin_name});
}
}

while (iterator.next() catch null) |bin_name| {
try writer.print(fmt, .{bin_name});
}
}
},
}
}
Expand Down
33 changes: 33 additions & 0 deletions test/js/bun/http/serve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1509,3 +1509,36 @@ it("should work with dispose keyword", async () => {
}
expect(fetch(url)).rejects.toThrow();
});

it("should be able to stop in the middle of a file response", async () => {
async function doRequest(url: string) {
try {
const response = await fetch(url, { signal: AbortSignal.timeout(10) });
const read = (response.body as ReadableStream<any>).getReader();
while (true) {
const { value, done } = await read.read();
if (done) break;
}
expect(response.status).toBe(200);
} catch {}
}
const fixture = join(import.meta.dir, "server-bigfile-send.fixture.js");
for (let i = 0; i < 3; i++) {
const process = Bun.spawn([bunExe(), fixture], {
env: bunEnv,
stderr: "inherit",
stdout: "pipe",
stdin: "ignore",
});
const { value } = await process.stdout.getReader().read();
const url = new TextDecoder().decode(value).trim();
const requests = [];
for (let j = 0; j < 5_000; j++) {
requests.push(doRequest(url));
}
// only await for 1k requests (and kill the process)
await Promise.all(requests.slice(0, 1_000));
expect(process.exitCode || 0).toBe(0);
process.kill();
}
}, 60_000);
13 changes: 13 additions & 0 deletions test/js/bun/http/server-bigfile-send.fixture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { serve, file } from "bun";
import { join } from "node:path";
const bigfile = join(import.meta.dir, "../../web/encoding/utf8-encoding-fixture.bin");
const server = serve({
port: 0,
async fetch() {
return new Response(file(bigfile), {
headers: { "Content-Type": "text/html" },
});
},
});

console.log(server.url.href);
Loading

0 comments on commit 986141a

Please sign in to comment.