Skip to content

Commit

Permalink
fix 16939 (#16991)
Browse files Browse the repository at this point in the history
  • Loading branch information
dylan-conway authored Feb 3, 2025
1 parent 00a5c4a commit 06b16fc
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 22 deletions.
24 changes: 12 additions & 12 deletions src/bun.js/api/bun/dns_resolver.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2519,7 +2519,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("resolve", "name", "non-empty string");
}

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);

switch (record_type) {
RecordType.A => {
Expand Down Expand Up @@ -2582,7 +2582,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("reverse", "ip", "non-empty string");
}

const ip_slice = ip_str.toSliceClone(globalThis, bun.default_allocator);
const ip_slice = try ip_str.toSliceClone(globalThis, bun.default_allocator);
const ip = ip_slice.slice();
const channel: *c_ares.Channel = switch (this.getChannel()) {
.result => |res| res,
Expand Down Expand Up @@ -2718,7 +2718,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("resolveSrv", "hostname", "non-empty string");
}

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_ares_srv_reply, "srv", name.slice(), globalThis);
}

Expand All @@ -2744,7 +2744,7 @@ pub const DNSResolver = struct {
return .zero;
};

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_ares_soa_reply, "soa", name.slice(), globalThis);
}

Expand Down Expand Up @@ -2774,7 +2774,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("resolveCaa", "hostname", "non-empty string");
}

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_ares_caa_reply, "caa", name.slice(), globalThis);
}

Expand All @@ -2800,7 +2800,7 @@ pub const DNSResolver = struct {
return .zero;
};

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_hostent, "ns", name.slice(), globalThis);
}

Expand Down Expand Up @@ -2830,7 +2830,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("resolvePtr", "hostname", "non-empty string");
}

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_hostent, "ptr", name.slice(), globalThis);
}

Expand Down Expand Up @@ -2860,7 +2860,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("resolveCname", "hostname", "non-empty string");
}

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_hostent, "cname", name.slice(), globalThis);
}

Expand Down Expand Up @@ -2890,7 +2890,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("resolveMx", "hostname", "non-empty string");
}

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_ares_mx_reply, "mx", name.slice(), globalThis);
}

Expand Down Expand Up @@ -2920,7 +2920,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("resolveNaptr", "hostname", "non-empty string");
}

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_ares_naptr_reply, "naptr", name.slice(), globalThis);
}

Expand Down Expand Up @@ -2950,7 +2950,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("resolveTxt", "hostname", "non-empty string");
}

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_ares_txt_reply, "txt", name.slice(), globalThis);
}

Expand Down Expand Up @@ -2980,7 +2980,7 @@ pub const DNSResolver = struct {
return globalThis.throwInvalidArgumentType("resolveAny", "hostname", "non-empty string");
}

const name = name_str.toSliceClone(globalThis, bun.default_allocator);
const name = try name_str.toSliceClone(globalThis, bun.default_allocator);
return this.doResolveCAres(c_ares.struct_any_reply, "any", name.slice(), globalThis);
}

Expand Down
14 changes: 10 additions & 4 deletions src/bun.js/bindings/bindings.zig
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,13 @@ pub const ZigString = extern struct {
return !this.allocator.isNull();
}

pub fn clone(this: Slice, allocator: std.mem.Allocator) !Slice {
pub fn toOwned(this: Slice, allocator: std.mem.Allocator) OOM!Slice {
const duped = try allocator.dupe(u8, this.ptr[0..this.len]);
return .{ .allocator = .init(allocator), .ptr = duped.ptr, .len = this.len };
}

// TODO: this is identical to `cloneIfNeeded`
pub fn clone(this: Slice, allocator: std.mem.Allocator) OOM!Slice {
if (this.isAllocated()) {
return Slice{ .allocator = this.allocator, .ptr = this.ptr, .len = this.len };
}
Expand Down Expand Up @@ -951,10 +957,10 @@ pub const ZigString = extern struct {
};
}

pub fn toSliceClone(this: ZigString, allocator: std.mem.Allocator) Slice {
pub fn toSliceClone(this: ZigString, allocator: std.mem.Allocator) OOM!Slice {
if (this.len == 0)
return Slice.empty;
const buffer = this.toOwnedSlice(allocator) catch unreachable;
const buffer = try this.toOwnedSlice(allocator);
return Slice{
.allocator = NullableAllocator.init(allocator),
.ptr = buffer.ptr,
Expand Down Expand Up @@ -1983,7 +1989,7 @@ pub const JSString = extern struct {
this: *JSString,
global: *JSGlobalObject,
allocator: std.mem.Allocator,
) ZigString.Slice {
) JSError!ZigString.Slice {
var str = ZigString.init("");
this.toZigString(global, &str);
return str.toSliceClone(allocator);
Expand Down
25 changes: 19 additions & 6 deletions src/bun.js/webcore/blob.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3489,10 +3489,15 @@ pub const Blob = struct {
// milliseconds since ECMAScript epoch
last_modified: JSC.JSTimeType = JSC.init_timestamp,

pub fn unlink(this: *const FileStore, globalThis: *JSC.JSGlobalObject) JSValue {
pub fn unlink(this: *const FileStore, globalThis: *JSC.JSGlobalObject) bun.JSError!JSValue {
return switch (this.pathlike) {
.path => |path_like| JSC.Node.Async.unlink.create(globalThis, undefined, .{
.path = .{ .encoded_slice = ZigString.init(path_like.slice()).toSliceClone(bun.default_allocator) },
.path = .{
.encoded_slice = switch (path_like) {
.encoded_slice => |slice| try slice.toOwned(bun.default_allocator),
else => try ZigString.init(path_like.slice()).toSliceClone(bun.default_allocator),
},
},
}, globalThis.bunVM()),
.fd => JSC.JSPromise.resolvedPromiseValue(globalThis, globalThis.createInvalidArgs("Is not possible to unlink a file descriptor", .{})),
};
Expand Down Expand Up @@ -4750,15 +4755,23 @@ pub const Blob = struct {
comptime {
_ = Bun__Blob__getSizeForBindings;
}
pub fn getStat(this: *Blob, globalThis: *JSC.JSGlobalObject, callback: *JSC.CallFrame) JSC.JSValue {
pub fn getStat(this: *Blob, globalThis: *JSC.JSGlobalObject, callback: *JSC.CallFrame) bun.JSError!JSC.JSValue {
const store = this.store orelse return JSC.JSValue.jsUndefined();
// TODO: make this async for files
return switch (store.data) {
.file => |*file| {
return switch (file.pathlike) {
.path => |path_like| JSC.Node.Async.stat.create(globalThis, undefined, .{
.path = .{ .encoded_slice = ZigString.init(path_like.slice()).toSliceClone(bun.default_allocator) },
}, globalThis.bunVM()),
.path => |path_like| {
return JSC.Node.Async.stat.create(globalThis, undefined, .{
.path = .{
.encoded_slice = switch (path_like) {
// it's already converted to utf8
.encoded_slice => |slice| try slice.toOwned(bun.default_allocator),
else => try ZigString.init(path_like.slice()).toSliceClone(bun.default_allocator),
},
},
}, globalThis.bunVM());
},
.fd => |fd| JSC.Node.Async.fstat.create(globalThis, undefined, .{ .fd = fd }, globalThis.bunVM()),
};
},
Expand Down
23 changes: 23 additions & 0 deletions test/js/bun/util/bun-file.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { test, expect } from "bun:test";
import { tmpdirSync } from "harness";
import { join } from "path";

test("delete() and stat() should work with unicode paths", async () => {
const testDir = tmpdirSync();
const filename = join(testDir, "🌟.txt");

expect(async () => {
await Bun.file(filename).delete();
}).toThrow(`ENOENT: no such file or directory, unlink '${filename}'`);

expect(async () => {
await Bun.file(filename).stat();
}).toThrow(`ENOENT: no such file or directory, stat '${filename}'`);

await Bun.write(filename, "HI");

expect(await Bun.file(filename).stat()).toMatchObject({ size: 2 });
expect(await Bun.file(filename).delete()).toBe(undefined);

expect(await Bun.file(filename).exists()).toBe(false);
});

0 comments on commit 06b16fc

Please sign in to comment.