diff options
author | 2023-08-31 17:33:08 -0700 | |
---|---|---|
committer | 2023-08-31 17:33:08 -0700 | |
commit | fef70f2473daefe242c80b9f3f34ef67396efaef (patch) | |
tree | 2f6dce4958d0a954115b6279deef418d9c8c340e | |
parent | bd7262f037589a69be8b5fb2f705666309c32b86 (diff) | |
download | bun-fef70f2473daefe242c80b9f3f34ef67396efaef.tar.gz bun-fef70f2473daefe242c80b9f3f34ef67396efaef.tar.zst bun-fef70f2473daefe242c80b9f3f34ef67396efaef.zip |
get name if not provided in `FormData.append` (#4434)
* get file name from blob if not provided
* add test
* another test
* format
-rw-r--r-- | bench/snippets/cp-r.mjs | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/JSDOMFormData.cpp | 10 | ||||
-rw-r--r-- | src/bun.js/webcore/blob.zig | 9 | ||||
-rw-r--r-- | test/js/web/html/FormData.test.ts | 30 |
4 files changed, 45 insertions, 5 deletions
diff --git a/bench/snippets/cp-r.mjs b/bench/snippets/cp-r.mjs index 78fbb2711..a5fe6d84f 100644 --- a/bench/snippets/cp-r.mjs +++ b/bench/snippets/cp-r.mjs @@ -1,4 +1,3 @@ import { cp } from "fs/promises"; await cp(process.argv[2], process.argv[3], { recursive: true }); - diff --git a/src/bun.js/bindings/webcore/JSDOMFormData.cpp b/src/bun.js/bindings/webcore/JSDOMFormData.cpp index 09a0a6c08..fdb71341c 100644 --- a/src/bun.js/bindings/webcore/JSDOMFormData.cpp +++ b/src/bun.js/bindings/webcore/JSDOMFormData.cpp @@ -286,6 +286,8 @@ static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_append1Body(JSC RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.append(WTFMove(name), WTFMove(value)); }))); } +extern "C" BunString Blob__getFileNameString(void* impl); + static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_append2Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); @@ -298,10 +300,6 @@ static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_append2Body(JSC RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - EnsureStillAliveScope argument2 = callFrame->argument(2); - auto filename = argument2.value().isUndefined() ? String() : convert<IDLUSVString>(*lexicalGlobalObject, argument2.value()); - RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); - RefPtr<Blob> blobValue = nullptr; if (argument1.value().inherits<JSBlob>()) { blobValue = Blob::create(argument1.value()); @@ -312,6 +310,10 @@ static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_append2Body(JSC } RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->argument(2); + auto filename = argument2.value().isUndefined() ? Bun::toWTFString(Blob__getFileNameString(blobValue->impl())) : convert<IDLUSVString>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.append(WTFMove(name), WTFMove(blobValue), WTFMove(filename)); }))); } diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig index 25f762e97..54c37e679 100644 --- a/src/bun.js/webcore/blob.zig +++ b/src/bun.js/webcore/blob.zig @@ -510,11 +510,20 @@ pub const Blob = struct { this.finalize(); } + export fn Blob__getFileNameString(this: *Blob) callconv(.C) bun.String { + if (this.getFileName()) |filename| { + return bun.String.fromBytes(filename); + } + + return bun.String.empty; + } + comptime { _ = Blob__dupeFromJS; _ = Blob__destroy; _ = Blob__dupe; _ = Blob__setAsFile; + _ = Blob__getFileNameString; } pub fn writeFormatForSize(size: usize, writer: anytype, comptime enable_ansi_colors: bool) !void { diff --git a/test/js/web/html/FormData.test.ts b/test/js/web/html/FormData.test.ts index c742bd33e..5e4861bc8 100644 --- a/test/js/web/html/FormData.test.ts +++ b/test/js/web/html/FormData.test.ts @@ -36,6 +36,36 @@ describe("FormData", () => { expect(formData.getAll("foo")[0]).toBe("bar"); }); + it("should get filename from file", async () => { + const blob = new Blob(["bar"]); + const formData = new FormData(); + formData.append("foo", blob); + // @ts-expect-error + expect(formData.get("foo").name).toBeUndefined(); + formData.append("foo2", new File([blob], "foo.txt")); + // @ts-expect-error + expect(formData.get("foo2").name).toBe("foo.txt"); + }); + + it("should use the correct filenames", async () => { + const blob = new Blob(["bar"]) as any; + const form = new FormData(); + form.append("foo", blob); + expect(blob.name).toBeUndefined(); + + let b1 = form.get("foo") as any; + expect(blob.name).toBeUndefined(); + expect(b1.name).toBeUndefined(); + + form.set("foo", b1, "foo.txt"); + expect(blob.name).toBeUndefined(); + expect(b1.name).toBeUndefined(); + + b1 = form.get("foo") as Blob; + expect(blob.name).toBeUndefined(); + expect(b1.name).toBe("foo.txt"); + }); + const multipartFormDataFixturesRawBody = [ { name: "simple", |