-
Couldn't load subscription status.
- Fork 279
Fetch + ReadableStream #972
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
Conversation
src/browser/fetch/Headers.zig
Outdated
|
|
||
| pub fn _get(self: *const Headers, header: []const u8, page: *Page) !?[]const u8 { | ||
| const arena = page.arena; | ||
| const key = try std.ascii.allocLowerString(arena, header); |
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.
can use the call_arena here, as you don't need the key to outlive this function call.
src/browser/fetch/Headers.zig
Outdated
| const key = try std.ascii.allocLowerString(arena, header); | ||
|
|
||
| const value = (self.headers.getEntry(key) orelse return null).value_ptr.*; | ||
| return try arena.dupe(u8, value); |
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.
You don't need to dupe this value at all, the string will get copied by v8. you can return self.headers.get(key) directly.
| done: bool, | ||
|
|
||
| pub fn get_value(self: *const ReadableStreamReadResult, page: *Page) !?[]const u8 { | ||
| return if (self.value) |value| try page.arena.dupe(u8, value) else null; |
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.
Probably don't need to dupe this:
return self.value;| switch (stream.state) { | ||
| .readable => { | ||
| if (stream.queue.items.len > 0) { | ||
| const data = self.stream.queue.orderedRemove(0); |
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.
This is O(N), right? I have no clue what these streams are used for, so we know how big the queues (a) typically are and (b) can grow to?
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.
Yes it is. Will circle back on this, mainly was waiting for us to go to 0.15.1 because a lot of the FIFO stuff was removed. Would be nice if we had our own nice Queue impl (or maybe I just use the PriorityQueue and always return .eq 🤷)
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.
@mookums Can you address this change now?
| }, | ||
| .closed => |_| { | ||
| if (stream.queue.items.len > 0) { | ||
| const data = try page.arena.dupe(u8, self.stream.queue.orderedRemove(0)); |
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.
If the value is dupe'd using the page.arena when being inserted, I don't think you'll ever need to dupe it again (certainly not with the same arena).
|
I tried to fetch http://127.0.0.1:1234/campfire-commerce/ and I get a |
8c8ba1e to
47aa966
Compare
|
I'm testing the branch and comparing results w/ I found a difference fetching https://fr.pinterest.com/ |
src/browser/fetch/Request.zig
Outdated
| self.body, | ||
| .{}, | ||
| ) catch |e| { | ||
| log.warn(.browser, "invalid json", .{ .err = e, .source = "Request" }); |
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.
You should create and use a .fetch domain for all fetch's logs
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.
This should be a debug or info. It's almost certainly a valid JS error that we can't do anything about. warn+ should be for things we can action.
|
Same with https://jobs.lightpanda.io/ |
|
Both of those resolved with 4413f68. |
src/browser/fetch/Request.zig
Outdated
| self.body, | ||
| .{}, | ||
| ) catch |e| { | ||
| log.warn(.browser, "invalid json", .{ .err = e, .source = "Request" }); |
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.
This should be a debug or info. It's almost certainly a valid JS error that we can't do anything about. warn+ should be for things we can action.
|
Ready for review by whoever, just don't merge yet as I'm going to migrate the tests to the new htmlRunner. |
|
We have a hug memory regression:
|
Fixed I believe, was a Persistent |
src/browser/fetch/fetch.zig
Outdated
|
|
||
| const resolver = Env.PromiseResolver{ | ||
| .js_context = page.main_context, | ||
| .resolver = v8.PromiseResolver.init(page.main_context.v8_context), |
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.
No other part of the WebAPI that needs to dig this deep into the JS implementation. The fetch code does this 10 times. Surely there's a way to clean this up and make it easier and less v8-specific to create promises
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.
I changed it so all instances of this pattern now use the Env.PersistentPromiseResolver which should make it less v8 specific to use these.
src/browser/fetch/fetch.zig
Outdated
| }; | ||
|
|
||
| // Add destructor callback for FetchContext. | ||
| try page.main_context.destructor_callbacks.append(arena, Env.DestructorCallback.init(fetch_ctx)); |
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.
This isn't ideal. Really reaching into an implementation details. Do we really need to reject the promise on page shutdown?
The other issue, that we talked about, is that if you don't cancel the transfer, then when the page does it, the errorCallback is called, and at that point, the context is aborted. But I think we can make this safer. (Although, I notice now that the errorCallback doesn't seem to be doing anything)
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.
Changed this so it only rejects the promise if we have an error that isn't error.Abort which is what we throw when the page is closed (I think). This allows us to just ditch using the destructor callbacks entirely.
This defaults to Auto, which means it runs when the call stack reaches 0. It appears that both Node and Deno set this to explicit. I don't really understand why Auto doesn't work. It says the call stack is the C++/C callstack, and I don't see what would block the current code from reaching a depth of 0. Still, we already have explicit calls to performMicrotasksCheckpoint which ties it holistically with our scheduler, so having it be explicit like this should...well make it more explicit This broke a test, but since the tests are being redone in the [fetch PR](#972) I simply removed the offending one.
bd4dd38 to
2a7a8bc
Compare
This implements
fetchin Zig, allowing us to also gain access to theReadableStreamAPI.