aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-07-12 22:28:14 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-07-12 22:46:27 -0700
commitd3963d6ea2f8e1065152060566e21de69b41d5d4 (patch)
tree8d9e55264badce3b0f4f76ac97c357b74ec853f3
parent0592b1dbed2459f35959f512d0050d1246c9e950 (diff)
downloadbun-d3963d6ea2f8e1065152060566e21de69b41d5d4.tar.gz
bun-d3963d6ea2f8e1065152060566e21de69b41d5d4.tar.zst
bun-d3963d6ea2f8e1065152060566e21de69b41d5d4.zip
[bun.js] Fix GC bug with `fetch`
-rw-r--r--src/bun.js/webcore/response.zig97
1 files changed, 29 insertions, 68 deletions
diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig
index 056f8e2fd..6171468b1 100644
--- a/src/bun.js/webcore/response.zig
+++ b/src/bun.js/webcore/response.zig
@@ -671,17 +671,14 @@ pub const Fetch = struct {
);
pub const FetchTasklet = struct {
- promise: *JSInternalPromise = undefined,
+ promise: *JSPromise = undefined,
http: HTTPClient.AsyncHTTP = undefined,
status: Status = Status.pending,
javascript_vm: *VirtualMachine = undefined,
global_this: *JSGlobalObject = undefined,
empty_request_body: MutableString = undefined,
- // pooled_body: *BodyPool.Node = undefined,
- this_object: js.JSObjectRef = null,
- resolve: js.JSObjectRef = null,
- reject: js.JSObjectRef = null,
+
context: FetchTaskletContext = undefined,
response_buffer: MutableString = undefined,
@@ -706,32 +703,34 @@ pub const Fetch = struct {
pub fn onDone(this: *FetchTasklet) void {
if (comptime JSC.is_bindgen)
unreachable;
- var args = [1]js.JSValueRef{undefined};
-
- var callback_object = switch (this.http.state.load(.Monotonic)) {
- .success => this.resolve,
- .fail => this.reject,
- else => unreachable,
- };
- args[0] = switch (this.http.state.load(.Monotonic)) {
- .success => this.onResolve().asObjectRef(),
- .fail => this.onReject().asObjectRef(),
+ const globalThis = this.global_this;
+ const promise = this.promise;
+ const state = this.http.state.load(.Monotonic);
+ const result = switch (state) {
+ .success => this.onResolve(),
+ .fail => this.onReject(),
else => unreachable,
};
- _ = js.JSObjectCallAsFunction(this.global_this.ref(), callback_object, null, 1, &args, null);
-
this.release();
+ const promise_value = promise.asValue(globalThis);
+ promise_value.unprotect();
+
+ switch (state) {
+ .success => {
+ promise.resolve(globalThis, result);
+ },
+ .fail => {
+ promise.reject(globalThis, result);
+ },
+ else => unreachable,
+ }
}
pub fn reset(_: *FetchTasklet) void {}
pub fn release(this: *FetchTasklet) void {
- js.JSValueUnprotect(this.global_this.ref(), this.resolve);
- js.JSValueUnprotect(this.global_this.ref(), this.reject);
- js.JSValueUnprotect(this.global_this.ref(), this.this_object);
-
this.global_this = undefined;
this.javascript_vm = undefined;
this.promise = undefined;
@@ -740,43 +739,13 @@ pub const Fetch = struct {
// BodyPool.release(pooled);
// this.pooled_body = undefined;
this.http = undefined;
- this.this_object = null;
- this.resolve = null;
- this.reject = null;
+
Pool.release(@fieldParentPtr(Pool.Node, "data", this));
}
- pub const FetchResolver = struct {
- pub fn call(
- _: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: usize,
- arguments: [*c]const js.JSValueRef,
- _: js.ExceptionRef,
- ) callconv(.C) js.JSObjectRef {
- return JSPrivateDataPtr.from(js.JSObjectGetPrivate(arguments[0]))
- .get(FetchTaskletContext).?.tasklet.onResolve().asObjectRef();
- // return js.JSObjectGetPrivate(arguments[0]).? .tasklet.onResolve().asObjectRef();
- }
- };
-
- pub const FetchRejecter = struct {
- pub fn call(
- _: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: usize,
- arguments: [*c]const js.JSValueRef,
- _: js.ExceptionRef,
- ) callconv(.C) js.JSObjectRef {
- return JSPrivateDataPtr.from(js.JSObjectGetPrivate(arguments[0]))
- .get(FetchTaskletContext).?.tasklet.onReject().asObjectRef();
- }
- };
-
pub fn onReject(this: *FetchTasklet) JSValue {
if (this.blob_store) |store| {
+ this.blob_store = null;
store.deref();
}
const fetch_error = std.fmt.allocPrint(
@@ -795,6 +764,7 @@ pub const Fetch = struct {
var http_response = this.http.response.?;
var response = allocator.create(Response) catch unreachable;
if (this.blob_store) |store| {
+ this.blob_store = null;
store.deref();
}
response.* = Response{
@@ -859,7 +829,6 @@ pub const Fetch = struct {
request_body_store: ?*Blob.Store,
) !*FetchTasklet.Pool.Node {
var node = try get(allocator, method, url, headers, headers_buf, request_body, timeout, request_body_store);
- node.data.promise = JSInternalPromise.create(global);
node.data.global_this = global;
node.data.http.callback = callback;
@@ -883,7 +852,7 @@ pub const Fetch = struct {
_: js.JSObjectRef,
_: js.JSObjectRef,
arguments: []const js.JSValueRef,
- exception: js.ExceptionRef,
+ _: js.ExceptionRef,
) js.JSObjectRef {
var globalThis = ctx.ptr();
@@ -983,11 +952,6 @@ pub const Fetch = struct {
header_entries = head.entries;
header_buf = head.buf.items;
}
- var resolve = js.JSObjectMakeFunctionWithCallback(ctx, null, Fetch.FetchTasklet.FetchResolver.call);
- var reject = js.JSObjectMakeFunctionWithCallback(ctx, null, Fetch.FetchTasklet.FetchRejecter.call);
-
- js.JSValueProtect(ctx, resolve);
- js.JSValueProtect(ctx, reject);
var request_body: ?*MutableString = null;
if (body.list.items.len > 0) {
@@ -1008,15 +972,12 @@ pub const Fetch = struct {
std.time.ns_per_hour,
blob_store,
) catch unreachable;
- queued.data.this_object = js.JSObjectMake(ctx, null, JSPrivateDataPtr.from(&queued.data.context).ptr());
- js.JSValueProtect(ctx, queued.data.this_object);
-
- var promise = js.JSObjectMakeDeferredPromise(ctx, &resolve, &reject, exception);
- queued.data.reject = reject;
- queued.data.resolve = resolve;
+ const promise = JSC.JSPromise.create(ctx);
+ queued.data.promise = promise;
+ const promise_value = promise.asValue(ctx);
+ promise_value.protect();
- return promise;
- // queued.data.promise.create(globalThis: *JSGlobalObject)
+ return promise_value.asObjectRef();
}
};