Repository navigation
Fixes #7001 #7861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #7001 #7861
Changes from all commits
6da49ae
df50338
40cdfed
bc797a1
ad92702
ebdcc51
99aef8c
ca0710a
e7f747c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,9 +52,12 @@ pub const ReadableStream = struct { | |
|
|
||
| pub const Strong = struct { | ||
| held: JSC.Strong = .{}, | ||
| globalThis: ?*JSGlobalObject = null, | ||
|
|
||
| pub fn init(this: ReadableStream, globalThis: *JSGlobalObject) !Strong { | ||
| pub fn globalThis(this: *const Strong) ?*JSGlobalObject { | ||
| return this.held.globalThis; | ||
| } | ||
|
|
||
| pub fn init(this: ReadableStream, global: *JSGlobalObject) !Strong { | ||
| switch (this.ptr) { | ||
| .Blob => |stream| { | ||
| try stream.parent().incrementCount(); | ||
|
|
@@ -68,15 +71,14 @@ pub const ReadableStream = struct { | |
| else => {}, | ||
| } | ||
| return .{ | ||
| .globalThis = globalThis, | ||
| .held = JSC.Strong.create(this.value, globalThis), | ||
| .held = JSC.Strong.create(this.value, global), | ||
| }; | ||
| } | ||
|
|
||
| pub fn get(this: *Strong) ?ReadableStream { | ||
| if (this.globalThis) |globalThis| { | ||
| if (this.globalThis()) |global| { | ||
| if (this.held.get()) |value| { | ||
| return ReadableStream.fromJS(value, globalThis); | ||
| return ReadableStream.fromJS(value, global); | ||
| } | ||
| } | ||
| return null; | ||
|
|
@@ -85,8 +87,7 @@ pub const ReadableStream = struct { | |
| pub fn deinit(this: *Strong) void { | ||
| if (this.get()) |readable| { | ||
| // decrement the ref count and if it's zero we auto detach | ||
| readable.detachIfPossible(this.globalThis.?); | ||
| this.globalThis = null; | ||
| readable.detachIfPossible(this.globalThis().?); | ||
| } | ||
| this.held.deinit(); | ||
| } | ||
|
|
@@ -96,10 +97,25 @@ pub const ReadableStream = struct { | |
| return this.value; | ||
| } | ||
|
|
||
| pub fn reloadTag(this: *ReadableStream, globalThis: *JSC.JSGlobalObject) void { | ||
| if (ReadableStream.fromJS(this.value, globalThis)) |stream| { | ||
| this.* = stream; | ||
| } else { | ||
| this.value.unprotect(); | ||
| this.* = .{ .ptr = .{ .Invalid = {} }, .value = .zero }; | ||
| } | ||
| } | ||
|
|
||
| pub fn toAnyBlob( | ||
| stream: *ReadableStream, | ||
| globalThis: *JSC.JSGlobalObject, | ||
| ) ?JSC.WebCore.AnyBlob { | ||
| if (stream.isDisturbed(globalThis)) { | ||
| return null; | ||
| } | ||
|
|
||
| stream.reloadTag(globalThis); | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the main cause We internally store the |
||
|
|
||
| switch (stream.ptr) { | ||
| .Blob => |blobby| { | ||
| var blob = JSC.WebCore.Blob.initWithStore(blobby.store, globalThis); | ||
|
|
@@ -147,14 +163,19 @@ pub const ReadableStream = struct { | |
|
|
||
| pub fn cancel(this: *const ReadableStream, globalThis: *JSGlobalObject) void { | ||
| JSC.markBinding(@src()); | ||
| this.value.unprotect(); | ||
| ReadableStream__cancel(this.value, globalThis); | ||
| this.value.unprotect(); | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moving this after out of caution that the value gets GC'd immediately after its unprotected |
||
| } | ||
|
|
||
| pub fn abort(this: *const ReadableStream, globalThis: *JSGlobalObject) void { | ||
| JSC.markBinding(@src()); | ||
| this.value.unprotect(); | ||
| ReadableStream__cancel(this.value, globalThis); | ||
| this.value.unprotect(); | ||
| } | ||
|
|
||
| pub fn forceDetach(this: *const ReadableStream, globalObject: *JSGlobalObject) void { | ||
| ReadableStream__detach(this.value, globalObject); | ||
| this.value.unprotect(); | ||
| } | ||
|
|
||
| /// Decrement Source ref count and detach the underlying stream if ref count is zero | ||
|
|
@@ -171,8 +192,8 @@ pub const ReadableStream = struct { | |
| }; | ||
|
|
||
| if (ref_count == 0) { | ||
| this.value.unprotect(); | ||
| ReadableStream__detach(this.value, globalThis); | ||
| this.value.unprotect(); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1323,7 +1323,7 @@ export function readableStreamDefaultControllerCallPullIfNeeded(controller) { | |
|
|
||
| export function isReadableStreamLocked(stream) { | ||
| $assert($isReadableStream(stream)); | ||
| return !!$getByIdDirectPrivate(stream, "reader"); | ||
| return !!$getByIdDirectPrivate(stream, "reader") || $getByIdDirectPrivate(stream, "bunNativePtr") === -1; | ||
| } | ||
|
|
||
| export function readableStreamDefaultControllerGetDesiredSize(controller) { | ||
|
|
@@ -1391,7 +1391,10 @@ export function readableStreamDefaultControllerClose(controller) { | |
| } | ||
|
|
||
| export function readableStreamClose(stream) { | ||
| $assert($getByIdDirectPrivate(stream, "state") === $streamReadable); | ||
| $assert( | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This fixes the debug assertion failure in the direct readable stream tests. |
||
| $getByIdDirectPrivate(stream, "state") === $streamReadable || | ||
| $getByIdDirectPrivate(stream, "state") === $streamClosing, | ||
| ); | ||
| $putByIdDirectPrivate(stream, "state", $streamClosed); | ||
| if (!$getByIdDirectPrivate(stream, "reader")) return; | ||
|
|
||
|
|
@@ -1640,6 +1643,8 @@ export function lazyLoadStream(stream, autoAllocateChunkSize) { | |
| $lazyStreamPrototypeMap.$set(nativeType, Prototype); | ||
| } | ||
|
|
||
| $putByIdDirectPrivate(stream, "disturbed", true); | ||
|
|
||
| const chunkSize = Prototype.startSync(nativePtr, autoAllocateChunkSize); | ||
| var drainValue; | ||
| const { drain: drainFn, deinit: deinitFn } = Prototype; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5269,7 +5269,7 @@ function createNativeStreamReadable(nativeType, Readable) { | |
|
|
||
| var ptr = this.#bunNativePtr; | ||
| $debug("ptr @ NativeReadable._read", ptr, this.__id); | ||
| if (ptr === 0) { | ||
| if (ptr === 0 || ptr === -1) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe adding some comments for what -1 and 0 mean (Locked/Detached) so we can remember next time |
||
| this.push(null); | ||
| return; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we also check isDisturbed in other places we call
useAsAnyBlob? like:bun/src/bun.js/webcore/response.zig
Line 1996 in 99aef8c
bun/src/bun.js/webcore/response.zig
Line 1779 in 99aef8c