aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.cpp26
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.h3
-rw-r--r--src/bun.js/bindings/generated_classes.zig4
-rw-r--r--src/bun.js/webcore/response.classes.ts4
-rw-r--r--test/bun.js/serve.test.ts22
5 files changed, 57 insertions, 2 deletions
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp
index 12db35785..f145424ed 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.cpp
+++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp
@@ -2128,6 +2128,10 @@ extern "C" EncodedJSValue RequestPrototype__getBlob(void* ptr, JSC::JSGlobalObje
JSC_DECLARE_HOST_FUNCTION(RequestPrototype__blobCallback);
+extern "C" JSC::EncodedJSValue RequestPrototype__getBody(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(RequestPrototype__bodyGetterWrap);
+
+
extern "C" JSC::EncodedJSValue RequestPrototype__getBodyUsed(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
JSC_DECLARE_CUSTOM_GETTER(RequestPrototype__bodyUsedGetterWrap);
@@ -2194,6 +2198,7 @@ STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSRequestPrototype, JSRequestPrototype::Base
static const HashTableValue JSRequestPrototypeTableValues[] = {
{ "arrayBuffer"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, RequestPrototype__arrayBufferCallback, 0 } } ,
{ "blob"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, RequestPrototype__blobCallback, 0 } } ,
+{ "body"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, RequestPrototype__bodyGetterWrap, 0 } } ,
{ "bodyUsed"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, RequestPrototype__bodyUsedGetterWrap, 0 } } ,
{ "cache"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, RequestPrototype__cacheGetterWrap, 0 } } ,
{ "clone"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, RequestPrototype__cloneCallback, 1 } } ,
@@ -2264,6 +2269,26 @@ JSC_DEFINE_HOST_FUNCTION(RequestPrototype__blobCallback, (JSGlobalObject * lexic
}
+JSC_DEFINE_CUSTOM_GETTER(RequestPrototype__bodyGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSRequest* thisObject = jsCast<JSRequest*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ if (JSValue cachedValue = thisObject->m_body.get())
+ return JSValue::encode(cachedValue);
+
+ JSC::JSValue result = JSC::JSValue::decode(
+ RequestPrototype__getBody(thisObject->wrapped(), globalObject)
+ );
+ RETURN_IF_EXCEPTION(throwScope, {});
+ thisObject->m_body.set(vm, thisObject, result);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
+}
+
+
JSC_DEFINE_CUSTOM_GETTER(RequestPrototype__bodyUsedGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
{
auto& vm = lexicalGlobalObject->vm();
@@ -2625,6 +2650,7 @@ void JSRequest::visitChildrenImpl(JSCell* cell, Visitor& visitor)
JSRequest* thisObject = jsCast<JSRequest*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
+ visitor.append(thisObject->m_body);
visitor.append(thisObject->m_headers);
visitor.append(thisObject->m_url);
}
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h
index bc0a2ec6f..7b10cfd20 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses.h
@@ -1182,7 +1182,8 @@ class JSRequest final : public JSC::JSDestructibleObject {
DECLARE_VISIT_CHILDREN;
- mutable JSC::WriteBarrier<JSC::Unknown> m_headers;
+ mutable JSC::WriteBarrier<JSC::Unknown> m_body;
+mutable JSC::WriteBarrier<JSC::Unknown> m_headers;
mutable JSC::WriteBarrier<JSC::Unknown> m_url;
};
class JSRequestPrototype final : public JSC::JSNonFinalObject {
diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig
index 0bc48964c..f6fa71fd5 100644
--- a/src/bun.js/bindings/generated_classes.zig
+++ b/src/bun.js/bindings/generated_classes.zig
@@ -752,6 +752,9 @@ pub const JSRequest = struct {
@compileLog("Expected Request.getArrayBuffer to be a callback");
if (@TypeOf(Request.getBlob) != CallbackType)
@compileLog("Expected Request.getBlob to be a callback");
+ if (@TypeOf(Request.getBody) != GetterType)
+ @compileLog("Expected Request.getBody to be a getter");
+
if (@TypeOf(Request.getBodyUsed) != GetterType)
@compileLog("Expected Request.getBodyUsed to be a getter");
@@ -800,6 +803,7 @@ pub const JSRequest = struct {
@export(Request.finalize, .{ .name = "RequestClass__finalize" });
@export(Request.getArrayBuffer, .{ .name = "RequestPrototype__getArrayBuffer" });
@export(Request.getBlob, .{ .name = "RequestPrototype__getBlob" });
+ @export(Request.getBody, .{ .name = "RequestPrototype__getBody" });
@export(Request.getBodyUsed, .{ .name = "RequestPrototype__getBodyUsed" });
@export(Request.getCache, .{ .name = "RequestPrototype__getCache" });
@export(Request.getCredentials, .{ .name = "RequestPrototype__getCredentials" });
diff --git a/src/bun.js/webcore/response.classes.ts b/src/bun.js/webcore/response.classes.ts
index 45df255e1..eeeaa8a60 100644
--- a/src/bun.js/webcore/response.classes.ts
+++ b/src/bun.js/webcore/response.classes.ts
@@ -8,6 +8,10 @@ export default [
klass: {},
JSType: "0b11101110",
proto: {
+ body: {
+ getter: "getBody",
+ cache: true,
+ },
text: { fn: "getText" },
json: { fn: "getJSON" },
arrayBuffer: { fn: "getArrayBuffer" },
diff --git a/test/bun.js/serve.test.ts b/test/bun.js/serve.test.ts
index 8961372c1..fb541da24 100644
--- a/test/bun.js/serve.test.ts
+++ b/test/bun.js/serve.test.ts
@@ -1,4 +1,4 @@
-import { file, serve } from "bun";
+import { file, readableStreamToText, serve } from "bun";
import { describe, expect, it } from "bun:test";
import { readFileSync } from "fs";
import { resolve } from "path";
@@ -12,6 +12,26 @@ class TestPass extends Error {
}
}
+describe("request body streaming", () => {
+ it("works", async () => {
+ var server = serve({
+ port: port++,
+ development: false,
+
+ async fetch(req: Request) {
+ const text = await readableStreamToText(req.body);
+ return new Response(text);
+ },
+ });
+
+ var res = await fetch(`http://localhost:${server.port}`, {
+ body: "hello",
+ method: "POST",
+ });
+ expect(await res.text()).toBe("hello");
+ });
+});
+
describe("streaming", () => {
describe("error handler", () => {
it("throw on pull reports an error and close the connection", async () => {