aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-23 04:26:49 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-23 04:26:49 -0700
commit07d77c1e00a3c74774ab4ea8c79d5bdeb0d9be4a (patch)
tree52b4a5c69ac1f0a5433166a92004a3134ba935f2
parent5e5f0bd2930a0e1a2f897ba6e857be05e8ca04f2 (diff)
downloadbun-07d77c1e00a3c74774ab4ea8c79d5bdeb0d9be4a.tar.gz
bun-07d77c1e00a3c74774ab4ea8c79d5bdeb0d9be4a.tar.zst
bun-07d77c1e00a3c74774ab4ea8c79d5bdeb0d9be4a.zip
[bun.js] Bun.write for macOS
-rw-r--r--integration/bunjs-only-snippets/html-rewriter.test.js13
-rw-r--r--integration/bunjs-only-snippets/response.file.test.js50
-rw-r--r--src/fallback.version2
-rw-r--r--src/javascript/jsc/api/html_rewriter.zig18
-rw-r--r--src/javascript/jsc/api/server.zig8
-rw-r--r--src/javascript/jsc/base.zig4
-rw-r--r--src/javascript/jsc/bindings/bindings.cpp16
-rw-r--r--src/javascript/jsc/bindings/bindings.zig11
-rw-r--r--src/javascript/jsc/bindings/headers-cpp.h2
-rw-r--r--src/javascript/jsc/bindings/headers.h4
-rw-r--r--src/javascript/jsc/bindings/headers.zig1
-rw-r--r--src/javascript/jsc/node/syscall.zig2
-rw-r--r--src/javascript/jsc/webcore/response.zig175
-rw-r--r--src/runtime.version2
14 files changed, 232 insertions, 76 deletions
diff --git a/integration/bunjs-only-snippets/html-rewriter.test.js b/integration/bunjs-only-snippets/html-rewriter.test.js
index bb63d8d25..a4ca965aa 100644
--- a/integration/bunjs-only-snippets/html-rewriter.test.js
+++ b/integration/bunjs-only-snippets/html-rewriter.test.js
@@ -42,6 +42,19 @@ describe("HTMLRewriter", () => {
expect(await output.text()).toBe("<div><blink>it worked!</blink></div>");
});
+ it("(from file) supports element handlers", async () => {
+ var rewriter = new HTMLRewriter();
+ rewriter.on("div", {
+ element(element) {
+ element.setInnerContent("<blink>it worked!</blink>", { html: true });
+ },
+ });
+ await Bun.write("/tmp/html-rewriter.txt.js", "<div>hello</div>");
+ var input = new Response(Bun.file("/tmp/html-rewriter.txt.js"));
+ var output = rewriter.transform(input);
+ expect(await output.text()).toBe("<div><blink>it worked!</blink></div>");
+ });
+
it("supports attribute iterator", async () => {
var rewriter = new HTMLRewriter();
var expected = [
diff --git a/integration/bunjs-only-snippets/response.file.test.js b/integration/bunjs-only-snippets/response.file.test.js
index f9cb886a2..6e1191433 100644
--- a/integration/bunjs-only-snippets/response.file.test.js
+++ b/integration/bunjs-only-snippets/response.file.test.js
@@ -10,12 +10,32 @@ it("Bun.write('out.txt', 'string')", async () => {
} catch (e) {}
}
- const out = await Bun.write("/tmp/out.txt", "string");
+ await Bun.write("/tmp/out.txt", "string");
+ const out = Bun.file("/tmp/out.txt");
expect(await out.text()).toBe("string");
expect(await out.text()).toBe(fs.readFileSync("/tmp/out.txt", "utf8"));
}
});
+it("Bun.write blob", async () => {
+ await Bun.write(
+ Bun.file("/tmp/response-file.test.txt"),
+ Bun.file(path.join(import.meta.dir, "fetch.js.txt"))
+ );
+ await Bun.write(Bun.file("/tmp/response-file.test.txt"), "blah blah blha");
+ await Bun.write(
+ Bun.file("/tmp/response-file.test.txt"),
+ new Uint32Array(1024)
+ );
+ await Bun.write("/tmp/response-file.test.txt", new Uint32Array(1024));
+ expect(
+ await Bun.write(
+ new TextEncoder().encode("/tmp/response-file.test.txt"),
+ new Uint32Array(1024)
+ )
+ ).toBe(new Uint32Array(1024).byteLength);
+});
+
it("Bun.file -> Bun.file", async () => {
try {
fs.unlinkSync(path.join("/tmp", "fetch.js.in"));
@@ -33,23 +53,22 @@ it("Bun.file -> Bun.file", async () => {
Bun.file("/tmp/fetch.js.out"),
Bun.file("/tmp/fetch.js.in")
);
- expect(await result.text()).toBe(text);
+ expect(await Bun.file("/tmp/fetch.js.out").text()).toBe(text);
}
{
- const result = await Bun.write(
+ await Bun.write(
Bun.file("/tmp/fetch.js.in").slice(0, (text.length / 2) | 0),
Bun.file("/tmp/fetch.js.out")
);
- expect(await result.text()).toBe(text.substring(0, (text.length / 2) | 0));
+ expect(await Bun.file("/tmp/fetch.js.in").text()).toBe(
+ text.substring(0, (text.length / 2) | 0)
+ );
}
{
- const result = await Bun.write(
- "/tmp/fetch.js.in",
- Bun.file("/tmp/fetch.js.out")
- );
- expect(await result.text()).toBe(text);
+ await Bun.write("/tmp/fetch.js.in", Bun.file("/tmp/fetch.js.out"));
+ expect(await Bun.file("/tmp/fetch.js.in").text()).toBe(text);
}
});
@@ -99,6 +118,19 @@ it("Response -> Bun.file", async () => {
expect(await response.text()).toBe(text);
});
+it("Bun.file -> Response", async () => {
+ // ensure the file doesn't already exist
+ try {
+ fs.unlinkSync("/tmp/fetch.js.out");
+ } catch {}
+
+ const file = path.join(import.meta.dir, "fetch.js.txt");
+ const text = fs.readFileSync(file, "utf8");
+ const resp = await fetch("https://example.com");
+ expect(await Bun.write("/tmp/fetch.js.out", resp)).toBe(text.length);
+ expect(await Bun.file("/tmp/fetch.js.out").text()).toBe(text);
+});
+
it("Response -> Bun.file -> Response -> text", async () => {
const file = path.join(import.meta.dir, "fetch.js.txt");
const text = fs.readFileSync(file, "utf8");
diff --git a/src/fallback.version b/src/fallback.version
index b07ec851e..36b21d826 100644
--- a/src/fallback.version
+++ b/src/fallback.version
@@ -1 +1 @@
-3c32b2da4ba87f18 \ No newline at end of file
+871e1d1d6a2e7805 \ No newline at end of file
diff --git a/src/javascript/jsc/api/html_rewriter.zig b/src/javascript/jsc/api/html_rewriter.zig
index a85a62ac8..a9f5f5d48 100644
--- a/src/javascript/jsc/api/html_rewriter.zig
+++ b/src/javascript/jsc/api/html_rewriter.zig
@@ -303,7 +303,7 @@ pub const HTMLRewriter = struct {
const is_pending = input.needsToReadFile();
defer if (!is_pending) input.detach();
- if (input.needsToReadFile()) {
+ if (is_pending) {
input.doReadFileInternal(*BufferOutputSink, sink, onFinishedLoadingWrap, global);
} else if (sink.runOutputSink(input.sharedView(), false)) |error_value| {
return error_value;
@@ -321,8 +321,6 @@ pub const HTMLRewriter = struct {
}
pub fn onFinishedLoading(sink: *BufferOutputSink, bytes: anyerror![]u8) void {
- var input = sink.input;
- defer input.detach();
const data = bytes catch |err| {
if (sink.response.body.value == .Locked and @ptrToInt(sink.response.body.value.Locked.task) == @ptrToInt(sink)) {
sink.response.body.value = .{ .Empty = .{} };
@@ -378,16 +376,10 @@ pub const HTMLRewriter = struct {
this.response.body.value = .{
.Blob = JSC.WebCore.Blob.init(bytes, this.bytes.allocator, this.global),
};
-
- if (prev_value.Locked.promise) |promise| {
- prev_value.Locked.promise = null;
- promise.asInternalPromise().?.resolve(this.global, JSC.JSValue.fromRef(
- Response.makeMaybePooled(
- this.global.ref(),
- this.response,
- ),
- ));
- }
+ prev_value.resolve(
+ &this.response.body.value,
+ this.global,
+ );
}
pub fn write(this: *BufferOutputSink, bytes: []const u8) void {
diff --git a/src/javascript/jsc/api/server.zig b/src/javascript/jsc/api/server.zig
index cd769c616..1360f4d52 100644
--- a/src/javascript/jsc/api/server.zig
+++ b/src/javascript/jsc/api/server.zig
@@ -298,7 +298,7 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
}
} else {
var sbytes: std.os.off_t = adjusted_count;
- const signed_offset = @bitCast(i64, this.sendfile.offset);
+ const signed_offset = @bitCast(i64, @as(u64, this.sendfile.offset));
// var sf_hdr_trailer: std.os.darwin.sf_hdtr = .{
// .headers = &separator_iovec,
@@ -320,9 +320,9 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
null,
0,
));
-
- this.sendfile.offset += sbytes;
- this.sendfile.remain -= @intCast(JSC.WebCore.Blob.SizeType, sbytes);
+ const wrote = @intCast(Blob.SizeType, sbytes);
+ this.sendfile.offset += wrote;
+ this.sendfile.remain -= wrote;
if (errcode != .AGAIN or this.aborted or this.sendfile.remain == 0 or sbytes == 0) {
if (errcode != .AGAIN and errcode != .SUCCESS) {
Output.prettyErrorln("Error: {s}", .{@tagName(errcode)});
diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig
index 0763b5b6d..13de8770d 100644
--- a/src/javascript/jsc/base.zig
+++ b/src/javascript/jsc/base.zig
@@ -1868,6 +1868,10 @@ pub const ArrayBuffer = extern struct {
return this.ptr[this.offset .. this.offset + this.len];
}
+ pub inline fn byteSlice(this: *const @This()) []u8 {
+ return this.ptr[this.offset .. this.offset + this.byte_len];
+ }
+
pub inline fn asU16(this: *const @This()) []u16 {
return std.mem.bytesAsSlice(u16, @alignCast(@alignOf([*]u16), this.ptr[this.offset..this.byte_len]));
}
diff --git a/src/javascript/jsc/bindings/bindings.cpp b/src/javascript/jsc/bindings/bindings.cpp
index 7036508c4..e4dbdc949 100644
--- a/src/javascript/jsc/bindings/bindings.cpp
+++ b/src/javascript/jsc/bindings/bindings.cpp
@@ -221,6 +221,12 @@ JSC__JSInternalPromise* JSC__JSValue__asInternalPromise(JSC__JSValue JSValue0)
JSC::JSValue value = JSC::JSValue::decode(JSValue0);
return JSC::jsCast<JSC::JSInternalPromise*>(value);
}
+
+JSC__JSPromise* JSC__JSValue__asPromise(JSC__JSValue JSValue0)
+{
+ JSC::JSValue value = JSC::JSValue::decode(JSValue0);
+ return JSC::jsCast<JSC::JSPromise*>(value);
+}
JSC__JSValue JSC__JSValue__createInternalPromise(JSC__JSGlobalObject* globalObject)
{
JSC::VM& vm = globalObject->vm();
@@ -1616,19 +1622,15 @@ int64_t JSC__JSValue__toInt64(JSC__JSValue val)
return result;
}
- if (auto* heapBigInt = _val.asHeapBigInt()) {
- if (heapBigInt != nullptr) {
+ if (_val.isHeapBigInt()) {
+
+ if (auto* heapBigInt = _val.asHeapBigInt()) {
return heapBigInt->toBigInt64(heapBigInt);
}
-
}
-
-
-
return _val.asAnyInt();
}
-
JSC__JSValue JSC__JSValue__createObject2(JSC__JSGlobalObject* globalObject, const ZigString* arg1,
const ZigString* arg2, JSC__JSValue JSValue3,
JSC__JSValue JSValue4)
diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig
index 0c9449037..0ddd11862 100644
--- a/src/javascript/jsc/bindings/bindings.zig
+++ b/src/javascript/jsc/bindings/bindings.zig
@@ -1836,6 +1836,7 @@ pub const JSValue = enum(u64) {
c_uint => @intCast(c_uint, toU32(this)),
c_int => @intCast(c_int, toInt32(this)),
?*JSInternalPromise => asInternalPromise(this),
+ ?*JSPromise => asPromise(this),
// TODO: BigUint64?
u64 => @as(u64, toU32(this)),
@@ -1935,6 +1936,14 @@ pub const JSValue = enum(u64) {
});
}
+ pub fn asPromise(
+ value: JSValue,
+ ) ?*JSPromise {
+ return cppFn("asPromise", .{
+ value,
+ });
+ }
+
pub fn jsNumber(number: anytype) JSValue {
return jsNumberWithType(@TypeOf(number), number);
}
@@ -2371,7 +2380,7 @@ pub const JSValue = enum(u64) {
return @intToPtr(*anyopaque, @enumToInt(this));
}
- pub const Extern = [_][]const u8{ "toInt64", "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "getReadableStreamState", "getWritableStreamState", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" };
+ pub const Extern = [_][]const u8{ "asPromise", "toInt64", "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "getReadableStreamState", "getWritableStreamState", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" };
};
extern "c" fn Microtask__run(*Microtask, *JSGlobalObject) void;
diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h
index bac4b0abf..421914228 100644
--- a/src/javascript/jsc/bindings/headers-cpp.h
+++ b/src/javascript/jsc/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1647946969
+//-- AUTOGENERATED FILE -- 1648033260
// clang-format off
#pragma once
diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h
index 4580be974..d04a3dc67 100644
--- a/src/javascript/jsc/bindings/headers.h
+++ b/src/javascript/jsc/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format: off
-//-- AUTOGENERATED FILE -- 1647946969
+//-- AUTOGENERATED FILE -- 1648033260
#pragma once
#include <stddef.h>
@@ -434,6 +434,8 @@ CPP_DECL JSC__JSCell* JSC__JSValue__asCell(JSC__JSValue JSValue0);
CPP_DECL JSC__JSInternalPromise* JSC__JSValue__asInternalPromise(JSC__JSValue JSValue0);
CPP_DECL double JSC__JSValue__asNumber(JSC__JSValue JSValue0);
CPP_DECL bJSC__JSObject JSC__JSValue__asObject(JSC__JSValue JSValue0);
+CPP_DECL JSC__JSPromise* JSC__JSValue__asPromise(JSC__JSValue JSValue0);
+CPP_DECL JSC__JSPromise* JSC__JSValue__asPromise(JSC__JSValue JSValue0);
CPP_DECL JSC__JSString* JSC__JSValue__asString(JSC__JSValue JSValue0);
CPP_DECL JSC__JSValue JSC__JSValue__createEmptyObject(JSC__JSGlobalObject* arg0, size_t arg1);
CPP_DECL JSC__JSValue JSC__JSValue__createInternalPromise(JSC__JSGlobalObject* arg0);
diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig
index a82822ed9..8298b8caa 100644
--- a/src/javascript/jsc/bindings/headers.zig
+++ b/src/javascript/jsc/bindings/headers.zig
@@ -273,6 +273,7 @@ pub extern fn JSC__JSValue__asCell(JSValue0: JSC__JSValue) [*c]JSC__JSCell;
pub extern fn JSC__JSValue__asInternalPromise(JSValue0: JSC__JSValue) [*c]JSC__JSInternalPromise;
pub extern fn JSC__JSValue__asNumber(JSValue0: JSC__JSValue) f64;
pub extern fn JSC__JSValue__asObject(JSValue0: JSC__JSValue) bJSC__JSObject;
+pub extern fn JSC__JSValue__asPromise(JSValue0: JSC__JSValue) [*c]JSC__JSPromise;
pub extern fn JSC__JSValue__asString(JSValue0: JSC__JSValue) [*c]JSC__JSString;
pub extern fn JSC__JSValue__createEmptyObject(arg0: [*c]JSC__JSGlobalObject, arg1: usize) JSC__JSValue;
pub extern fn JSC__JSValue__createInternalPromise(arg0: [*c]JSC__JSGlobalObject) JSC__JSValue;
diff --git a/src/javascript/jsc/node/syscall.zig b/src/javascript/jsc/node/syscall.zig
index 3bd6a8cf7..bac85cce4 100644
--- a/src/javascript/jsc/node/syscall.zig
+++ b/src/javascript/jsc/node/syscall.zig
@@ -328,7 +328,7 @@ pub fn copyfile(from: [:0]const u8, to: [:0]const u8, flags: c_int) Maybe(void)
unreachable;
}
-pub fn fcopyfile(fd_in: std.os.fd_t, fd_out: std.os.fd_t, flags: c_int) Maybe(void) {
+pub fn fcopyfile(fd_in: std.os.fd_t, fd_out: std.os.fd_t, flags: u32) Maybe(void) {
if (comptime !Environment.isMac) @compileError("macOS only");
while (true) {
diff --git a/src/javascript/jsc/webcore/response.zig b/src/javascript/jsc/webcore/response.zig
index 23885a0ea..0c9e71a85 100644
--- a/src/javascript/jsc/webcore/response.zig
+++ b/src/javascript/jsc/webcore/response.zig
@@ -157,6 +157,12 @@ pub const Response = struct {
status_text: string = "",
redirected: bool = false,
+ pub fn getBodyValue(
+ this: *Response,
+ ) *Body.Value {
+ return &this.body.value;
+ }
+
pub inline fn statusCode(this: *const Response) u16 {
return this.body.init.status_code;
}
@@ -1995,13 +2001,19 @@ pub const Blob = struct {
pub fn getFdMac(this: *This) AsyncIO.OpenError!JSC.Node.FileDescriptor {
var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
- this.opened_fd = AsyncIO.openSync(
- this.file_store.pathlike.path.sliceZ(&buf),
- open_flags_,
- ) catch |err| {
- this.errno = err;
- return err;
+ var path = if (@hasField(This, "file_store"))
+ this.file_store.pathlike.path.sliceZ(&buf)
+ else
+ this.file_blob.store.?.data.file.pathlike.path.sliceZ(&buf);
+
+ this.opened_fd = switch (JSC.Node.Syscall.open(path, open_flags_, JSC.Node.default_permission)) {
+ .result => |fd| fd,
+ .err => |err| {
+ this.errno = AsyncIO.asError(err.errno);
+ return @errSetCast(AsyncIO.OpenError, this.errno.?);
+ },
};
+
return this.opened_fd;
}
@@ -2437,8 +2449,8 @@ pub const Blob = struct {
onCompleteCallback: OnWriteFileCallback = undefined,
wrote: usize = 0,
- pub const ResultType = anyerror!Blob;
- pub const OnWriteFileCallback = fn (ctx: *anyopaque, blob: ResultType) void;
+ pub const ResultType = anyerror!SizeType;
+ pub const OnWriteFileCallback = fn (ctx: *anyopaque, count: ResultType) void;
pub usingnamespace FileOpenerMixin(WriteFile);
pub usingnamespace FileCloserMixin(WriteFile);
@@ -2522,6 +2534,7 @@ pub const Blob = struct {
var cb_ctx = this.onCompleteCtx;
this.bytes_blob.store.?.deref();
+ this.file_blob.store.?.deref();
if (this.errno) |err| {
bun.default_allocator.destroy(this);
@@ -2529,10 +2542,8 @@ pub const Blob = struct {
return;
}
- var blob = this.file_blob;
-
bun.default_allocator.destroy(this);
- cb(cb_ctx, blob);
+ cb(cb_ctx, @truncate(SizeType, this.wrote));
}
pub fn run(this: *WriteFile, task: *WriteFileTask) void {
this.runAsyncFrame = async this.runAsync(task);
@@ -2580,7 +2591,7 @@ pub const Blob = struct {
if (wrote_len == 0) break;
}
- this.file_blob.size = @truncate(SizeType, total_written);
+ this.wrote = @truncate(SizeType, total_written);
if (needs_close) {
this.doClose() catch {};
@@ -2613,7 +2624,7 @@ pub const Blob = struct {
globalThis: *JSGlobalObject,
- pub const ResultType = anyerror!Blob;
+ pub const ResultType = anyerror!SizeType;
pub const Callback = fn (ctx: *anyopaque, len: ResultType) void;
pub const CopyFilePromiseTask = JSC.ConcurrentPromiseTask(CopyFile);
@@ -2651,6 +2662,7 @@ pub const Blob = struct {
bun.default_allocator.free(bun.constStrToU8(this.source_file_store.pathlike.path.slice()));
}
}
+ this.store.?.deref();
bun.default_allocator.destroy(this);
}
@@ -2673,21 +2685,14 @@ pub const Blob = struct {
}
pub fn then(this: *CopyFile, promise: *JSC.JSInternalPromise) void {
- defer this.source_store.?.deref();
+ this.source_store.?.deref();
if (this.errno != null) {
this.reject(promise);
return;
}
- var blob = Blob{
- .offset = this.read_off,
- .size = this.read_len,
- .store = this.store,
- };
- blob.allocator = bun.default_allocator;
- var ptr = bun.default_allocator.create(Blob) catch unreachable;
- ptr.* = blob;
- promise.resolve(this.globalThis, JSC.JSValue.fromRef(Blob.Class.make(this.globalThis.ref(), ptr)));
+
+ promise.resolve(this.globalThis, JSC.JSValue.jsNumberFromUint64(this.read_len));
}
pub fn run(this: *CopyFile) void {
this.runAsync();
@@ -2802,14 +2807,23 @@ pub const Blob = struct {
pub fn doFCopyFile(this: *CopyFile) anyerror!void {
switch (JSC.Node.Syscall.fcopyfile(this.source_fd, this.destination_fd, os.system.COPYFILE_DATA)) {
- else => |errno| {
- this.errno = AsyncIO.asError(errno);
+ .err => |errno| {
+ this.errno = AsyncIO.asError(errno.errno);
return this.errno.?;
},
.result => {},
}
}
+ pub fn doClonefile(this: *CopyFile) anyerror!void {
+ switch (JSC.Node.Syscall.clonefile(this.destination_file_store.pathlike.path.sliceZAssume(), this.source_file_store.pathlike.path.sliceZAssume())) {
+ .err => |errno| {
+ return AsyncIO.asError(errno.errno);
+ },
+ .result => {},
+ }
+ }
+
pub fn runAsync(this: *CopyFile) void {
// defer task.onFinish();
@@ -2829,7 +2843,7 @@ pub const Blob = struct {
// First, we attempt to clonefile() on macOS
// This is the fastest way to copy a file.
if (comptime Environment.isMac) {
- if (this.offset == 0) {
+ if (this.offset == 0 and this.source_file_store.pathlike == .path and this.destination_file_store.pathlike == .path) {
do_clonefile: {
// stat the output file, make sure it:
@@ -2848,12 +2862,12 @@ pub const Blob = struct {
},
.err => |err| {
// If we can't stat it, we also can't copy it.
- this.errno = err;
+ this.errno = AsyncIO.asError(err.errno);
return;
},
}
- if (this.doCloneFile()) {
+ if (this.doClonefile()) {
if (this.max_length != Blob.max_size and this.max_length < @intCast(SizeType, stat_.?.size)) {
// If this fails...well, there's not much we can do about it.
_ = bun.C.truncate(
@@ -3448,11 +3462,11 @@ pub const Blob = struct {
pub const WriteFilePromise = struct {
promise: *JSPromise,
globalThis: *JSGlobalObject,
- pub fn run(handler: *@This(), blob_: Blob.Store.WriteFile.ResultType) void {
+ pub fn run(handler: *@This(), count: Blob.Store.WriteFile.ResultType) void {
var promise = handler.promise;
var globalThis = handler.globalThis;
bun.default_allocator.destroy(handler);
- var blob = blob_ catch |err| {
+ var wrote = count catch |err| {
var error_string = ZigString.init(
std.fmt.allocPrint(bun.default_allocator, "Failed to write file \"{s}\"", .{std.mem.span(@errorName(err))}) catch unreachable,
);
@@ -3461,10 +3475,7 @@ pub const Blob = struct {
return;
};
- var ptr = bun.default_allocator.create(Blob) catch unreachable;
- ptr.* = blob;
-
- promise.resolve(globalThis, JSC.JSValue.fromRef(Blob.Class.make(globalThis.ref(), ptr)));
+ promise.resolve(globalThis, JSC.JSValue.jsNumberFromUint64(wrote));
}
};
@@ -3775,7 +3786,7 @@ pub const Blob = struct {
JSC.JSValue.JSType.BigUint64Array,
JSC.JSValue.JSType.DataView,
=> {
- var buf = try bun.default_allocator.dupe(u8, top_value.asArrayBuffer(global).?.slice());
+ var buf = try bun.default_allocator.dupe(u8, top_value.asArrayBuffer(global).?.byteSlice());
return Blob.init(buf, bun.default_allocator, global);
},
@@ -3866,7 +3877,7 @@ pub const Blob = struct {
JSC.JSValue.JSType.DataView,
=> {
var buf = item.asArrayBuffer(global).?;
- joiner.append(buf.slice(), 0, null);
+ joiner.append(buf.byteSlice(), 0, null);
continue;
},
.Array, .DerivedArray => {
@@ -4073,6 +4084,15 @@ pub const Body = struct {
task: ?*anyopaque = null,
callback: ?fn (ctx: *anyopaque, value: *Value) void = null,
deinit: bool = false,
+ action: Action = Action.none,
+
+ pub const Action = enum {
+ none,
+ getText,
+ getJSON,
+ getArrayBuffer,
+ getBlob,
+ };
};
pub const Value = union(Tag) {
@@ -4091,6 +4111,47 @@ pub const Body = struct {
};
pub const empty = Value{ .Empty = .{} };
+
+ pub fn resolve(this: *Value, new: *Value, global: *JSGlobalObject) void {
+ if (this.* == .Locked) {
+ var locked = this.Locked;
+ if (locked.callback) |callback| {
+ locked.callback = null;
+ callback(locked.task.?, new);
+ }
+
+ if (locked.promise) |promise| {
+ var blob = new.use();
+
+ switch (locked.action) {
+ .getText => {
+ promise.asPromise().?.resolve(global, JSValue.fromRef(blob.getTextTransfer(global.ref())));
+ },
+ .getJSON => {
+ promise.asPromise().?.resolve(global, blob.toJSON(global));
+ blob.detach();
+ },
+ .getArrayBuffer => {
+ promise.asPromise().?.resolve(global, JSValue.fromRef(blob.getArrayBufferTransfer(global.ref())));
+ },
+ .getBlob => {
+ var ptr = bun.default_allocator.create(Blob) catch unreachable;
+ ptr.* = blob;
+ ptr.allocator = bun.default_allocator;
+ promise.asPromise().?.resolve(global, JSC.JSValue.fromRef(Blob.Class.make(global.ref(), ptr)));
+ },
+ else => {
+ var ptr = bun.default_allocator.create(Blob) catch unreachable;
+ ptr.* = blob;
+ ptr.allocator = bun.default_allocator;
+ promise.asInternalPromise().?.resolve(global, JSC.JSValue.fromRef(Blob.Class.make(global.ref(), ptr)));
+ },
+ }
+ JSC.C.JSValueUnprotect(global.ref(), promise.asObjectRef());
+ locked.promise = null;
+ }
+ }
+ }
pub fn slice(this: Value) []const u8 {
return switch (this) {
.Blob => this.Blob.sharedView(),
@@ -4118,8 +4179,9 @@ pub const Body = struct {
if (locked.promise) |promise| {
if (promise.asInternalPromise()) |internal| {
internal.reject(global, error_instance);
+ } else if (promise.asPromise()) |internal| {
+ internal.reject(global, error_instance);
}
-
JSC.C.JSValueUnprotect(global.ref(), promise.asObjectRef());
locked.promise = null;
}
@@ -4535,6 +4597,12 @@ pub const Request = struct {
);
}
+ pub fn getBodyValue(
+ this: *Request,
+ ) *Body.Value {
+ return &this.body;
+ }
+
pub fn getBodyUsed(
this: *Request,
_: js.JSContextRef,
@@ -4602,6 +4670,14 @@ fn BlobInterface(comptime Type: type) type {
_: []const js.JSValueRef,
_: js.ExceptionRef,
) js.JSValueRef {
+ var value = this.getBodyValue();
+ if (value.* == .Locked) {
+ value.Locked.action = .getText;
+ var promise = JSC.JSPromise.create(ctx.ptr());
+ value.Locked.promise = promise.asValue(ctx.ptr());
+ return value.Locked.promise.?.asObjectRef();
+ }
+
var blob = this.body.use();
return blob.getTextTransfer(ctx);
}
@@ -4614,6 +4690,14 @@ fn BlobInterface(comptime Type: type) type {
_: []const js.JSValueRef,
exception: js.ExceptionRef,
) js.JSValueRef {
+ var value = this.getBodyValue();
+ if (value.* == .Locked) {
+ value.Locked.action = .getJSON;
+ var promise = JSC.JSPromise.create(ctx.ptr());
+ value.Locked.promise = promise.asValue(ctx.ptr());
+ return value.Locked.promise.?.asObjectRef();
+ }
+
var blob = this.body.use();
return blob.getJSON(ctx, null, null, &.{}, exception);
}
@@ -4625,6 +4709,15 @@ fn BlobInterface(comptime Type: type) type {
_: []const js.JSValueRef,
_: js.ExceptionRef,
) js.JSValueRef {
+ var value = this.getBodyValue();
+
+ if (value.* == .Locked) {
+ value.Locked.action = .getArrayBuffer;
+ var promise = JSC.JSPromise.create(ctx.ptr());
+ value.Locked.promise = promise.asValue(ctx.ptr());
+ return value.Locked.promise.?.asObjectRef();
+ }
+
var blob = this.body.use();
return blob.getArrayBufferTransfer(ctx);
}
@@ -4637,6 +4730,14 @@ fn BlobInterface(comptime Type: type) type {
_: []const js.JSValueRef,
_: js.ExceptionRef,
) js.JSValueRef {
+ var value = this.getBodyValue();
+ if (value.* == .Locked) {
+ value.Locked.action = .getBlob;
+ var promise = JSC.JSPromise.create(ctx.ptr());
+ value.Locked.promise = promise.asValue(ctx.ptr());
+ return value.Locked.promise.?.asObjectRef();
+ }
+
var blob = this.body.use();
var ptr = getAllocator(ctx).create(Blob) catch unreachable;
ptr.* = blob;
diff --git a/src/runtime.version b/src/runtime.version
index fd95ea0a3..0bbf538da 100644
--- a/src/runtime.version
+++ b/src/runtime.version
@@ -1 +1 @@
-118e8e9b568841b0 \ No newline at end of file
+139d399765744be7 \ No newline at end of file