diff options
Diffstat (limited to 'src/javascript/jsc')
-rw-r--r-- | src/javascript/jsc/api/html_rewriter.zig | 6 | ||||
-rw-r--r-- | src/javascript/jsc/api/server.zig | 23 | ||||
-rw-r--r-- | src/javascript/jsc/javascript.zig | 2 | ||||
-rw-r--r-- | src/javascript/jsc/webcore/response.zig | 59 |
4 files changed, 72 insertions, 18 deletions
diff --git a/src/javascript/jsc/api/html_rewriter.zig b/src/javascript/jsc/api/html_rewriter.zig index c62a6503f..e314fc18d 100644 --- a/src/javascript/jsc/api/html_rewriter.zig +++ b/src/javascript/jsc/api/html_rewriter.zig @@ -216,7 +216,7 @@ pub const HTMLRewriter = struct { response.cloneInto(result, getAllocator(global.ref())); this.finalizeWithoutDestroy(); - return JSValue.fromRef(Response.Class.make(global.ref(), result)); + return JSValue.fromRef(Response.makeMaybePooled(global.ref(), result)); } var new_context = this.context; @@ -311,7 +311,7 @@ pub const HTMLRewriter = struct { }; return JSC.JSValue.fromRef( - Response.Class.make(sink.global.ref(), sink.response), + Response.makeMaybePooled(sink.global.ref(), sink.response), ); } @@ -327,7 +327,7 @@ pub const HTMLRewriter = struct { if (prev_value.Locked.promise) |promise| { prev_value.Locked.promise = null; promise.asInternalPromise().?.resolve(this.global, JSC.JSValue.fromRef( - Response.Class.make( + Response.makeMaybePooled( this.global.ref(), this.response, ), diff --git a/src/javascript/jsc/api/server.zig b/src/javascript/jsc/api/server.zig index 4b7805adb..8c64c112a 100644 --- a/src/javascript/jsc/api/server.zig +++ b/src/javascript/jsc/api/server.zig @@ -92,6 +92,7 @@ pub fn NewServer(comptime ssl_enabled: bool) type { app: *App = undefined, globalThis: *JSGlobalObject, default_server: URL = URL{ .host = "localhost", .port = "3000" }, + response_objects_pool: JSC.WebCore.Response.Pool = JSC.WebCore.Response.Pool{}, request_pool_allocator: std.mem.Allocator = undefined, @@ -116,6 +117,7 @@ pub fn NewServer(comptime ssl_enabled: bool) type { this.listener = socket; VirtualMachine.vm.uws_event_loop = uws.Loop.get(); + VirtualMachine.vm.response_objects_pool = &this.response_objects_pool; this.app.run(); } @@ -127,6 +129,7 @@ pub fn NewServer(comptime ssl_enabled: bool) type { method: HTTP.Method, aborted: bool = false, response_jsvalue: JSC.JSValue = JSC.JSValue.zero, + response_ptr: ?*JSC.WebCore.Response = null, blob: JSC.WebCore.Blob = JSC.WebCore.Blob{}, promise: ?*JSC.JSValue = null, response_headers: ?*JSC.WebCore.Headers.RefCountedHeaders = null, @@ -181,14 +184,13 @@ pub fn NewServer(comptime ssl_enabled: bool) type { .method = HTTP.Method.which(req.method()) orelse .GET, .server = server, }; - resp.onAborted(*RequestContext, onAbort, this); } pub fn onAbort(this: *RequestContext, _: *App.Response) void { this.aborted = true; this.req = undefined; if (!this.response_jsvalue.isEmpty()) { - JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.response_jsvalue.asObjectRef()); + this.server.response_objects_pool.push(this.server.globalThis, this.response_jsvalue); this.response_jsvalue = JSC.JSValue.zero; } } @@ -196,7 +198,7 @@ pub fn NewServer(comptime ssl_enabled: bool) type { pub fn finalize(this: *RequestContext) void { this.blob.detach(); if (!this.response_jsvalue.isEmpty()) { - JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.response_jsvalue.asObjectRef()); + this.server.response_objects_pool.push(this.server.globalThis, this.response_jsvalue); this.response_jsvalue = JSC.JSValue.zero; } @@ -213,11 +215,11 @@ pub fn NewServer(comptime ssl_enabled: bool) type { this.server.request_pool_allocator.destroy(this); } - pub fn render(this: *RequestContext, response: *JSC.WebCore.Response) void { + pub fn doRender(this: *RequestContext) void { if (this.aborted) { return; } - + var response = this.response_ptr.?; this.blob = response.body.use(); const status = response.statusCode(); @@ -236,9 +238,7 @@ pub fn NewServer(comptime ssl_enabled: bool) type { this.resp.writeStatus(std.fmt.bufPrint(&status_text_buf, "{d} HM", .{response.body.init.status_code}) catch unreachable); } - for (names) |name, i| { - this.resp.writeHeader(headers.asStr(name), headers.asStr(values[i])); - } + this.resp.writeHeaders(names, values, headers.buf.items); } if (status == 302 or status == 202 or this.blob.size == 0) { @@ -250,6 +250,12 @@ pub fn NewServer(comptime ssl_enabled: bool) type { this.resp.end(this.blob.sharedView(), false); this.finalize(); } + + pub fn render(this: *RequestContext, response: *JSC.WebCore.Response) void { + this.response_ptr = response; + this.resp.runCorked(*RequestContext, doRender, this); + this.response_ptr = null; + } }; pub fn onRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void { @@ -286,6 +292,7 @@ pub fn NewServer(comptime ssl_enabled: bool) type { } if (ctx.response_jsvalue.jsTypeLoose() == .JSPromise) { + resp.onAborted(*RequestContext, RequestContext.onAbort, ctx); JSC.VirtualMachine.vm.tick(); ctx.response_jsvalue.then( diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig index 4a8fefd3c..d0dcb9ddc 100644 --- a/src/javascript/jsc/javascript.zig +++ b/src/javascript/jsc/javascript.zig @@ -480,7 +480,7 @@ pub const VirtualMachine = struct { ref_strings: JSC.RefString.Map = undefined, source_mappings: SavedSourceMap = undefined, - + response_objects_pool: ?*Response.Pool = null, pub inline fn eventLoop(this: *VirtualMachine) *EventLoop { return this.event_loop; } diff --git a/src/javascript/jsc/webcore/response.zig b/src/javascript/jsc/webcore/response.zig index 778b22171..6e9859352 100644 --- a/src/javascript/jsc/webcore/response.zig +++ b/src/javascript/jsc/webcore/response.zig @@ -42,6 +42,42 @@ const JSPrinter = @import("../../../js_printer.zig"); const picohttp = @import("picohttp"); const StringJoiner = @import("../../../string_joiner.zig"); pub const Response = struct { + pub const Pool = struct { + response_objects_pool: [127]JSC.C.JSObjectRef = undefined, + response_objects_used: u8 = 0, + + pub fn get(this: *Pool, ptr: *Response) ?JSC.C.JSObjectRef { + if (this.response_objects_used > 0) { + var result = this.response_objects_pool[this.response_objects_used - 1]; + this.response_objects_used -= 1; + if (JSC.C.JSObjectSetPrivate(result, JSPrivateDataPtr.init(ptr).ptr())) { + return result; + } else { + JSC.C.JSValueUnprotect(VirtualMachine.vm.global.ref(), result); + } + } + + return null; + } + + pub fn push(this: *Pool, globalThis: *JSC.JSGlobalObject, object: JSC.JSValue) void { + var remaining = this.response_objects_pool[@minimum(this.response_objects_used, this.response_objects_pool.len)..]; + if (remaining.len == 0) { + JSC.C.JSValueUnprotect(globalThis.ref(), object.asObjectRef()); + return; + } + + if (object.as(Response)) |resp| { + _ = JSC.C.JSObjectSetPrivate(object.asObjectRef(), null); + + _ = resp.body.use(); + resp.finalize(); + remaining[0] = object.asObjectRef(); + this.response_objects_used += 1; + } + } + }; + pub const Constructor = JSC.NewConstructor( Response, .{ @@ -262,7 +298,18 @@ pub const Response = struct { _: js.ExceptionRef, ) js.JSValueRef { var cloned = this.clone(getAllocator(ctx)); - return Response.Class.make(ctx, cloned); + return Response.makeMaybePooled(ctx, cloned); + } + + pub fn makeMaybePooled(ctx: js.JSContextRef, ptr: *Response) JSC.C.JSObjectRef { + if (JSC.VirtualMachine.vm.response_objects_pool) |pool| { + if (pool.get(ptr)) |object| { + JSC.C.JSValueUnprotect(ctx, object); + return object; + } + } + + return Response.Class.make(ctx, ptr); } pub fn cloneInto(this: *const Response, new_response: *Response, allocator: std.mem.Allocator) void { @@ -410,7 +457,7 @@ pub const Response = struct { var ptr = response.allocator.create(Response) catch unreachable; ptr.* = response; - return Response.Class.make(ctx, ptr); + return Response.makeMaybePooled(ctx, ptr); } pub fn constructRedirect( _: void, @@ -462,7 +509,7 @@ pub const Response = struct { var ptr = response.allocator.create(Response) catch unreachable; ptr.* = response; - return Response.Class.make(ctx, ptr); + return Response.makeMaybePooled(ctx, ptr); } pub fn constructError( _: void, @@ -485,7 +532,7 @@ pub const Response = struct { .url = "", }; - return Response.Class.make( + return Response.makeMaybePooled( ctx, response, ); @@ -522,7 +569,7 @@ pub const Response = struct { .allocator = getAllocator(ctx), .url = "", }; - return Response.Class.make( + return Response.makeMaybePooled( ctx, response, ); @@ -753,7 +800,7 @@ pub const Fetch = struct { }, }, }; - return JSValue.fromRef(Response.Class.make(@ptrCast(js.JSContextRef, this.global_this), response)); + return JSValue.fromRef(Response.makeMaybePooled(@ptrCast(js.JSContextRef, this.global_this), response)); } pub fn get( |