mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-06-11 09:35:59 -04:00
Defer HTTP completion callbacks to next tick
Client.makeRequest used to call self.perform(0) after handing the transfer to libcurl. That perform() does two things: drives curl_multi_perform (so bytes hit the wire) AND drains curl_multi_info_read messages, which is what fires the user-facing header/data/done callbacks. The issue is that, even in non-cache cases, a request could be immediately resolved in libcurl, and thus callbacks executed synchronously. By only calling `curl_multi_perform` on a new request, we prevent this from happening.
This commit is contained in:
@@ -611,7 +611,15 @@ fn makeRequest(self: *Client, conn: *http.Connection, transfer: *Transfer) anyer
|
||||
return err;
|
||||
};
|
||||
}
|
||||
_ = try self.perform(0);
|
||||
|
||||
// Start the request (and move along any other request). This used to call
|
||||
// self.perform(0) but that can also execute callbacks. Normally, that
|
||||
// wouldn't be so bad. But curl can synchronously fire callbacks for the
|
||||
// request we JUST added, which we do not want (it results in incorrect
|
||||
// execution).
|
||||
self.performing = true;
|
||||
defer self.performing = false;
|
||||
_ = try self.handles.perform();
|
||||
}
|
||||
|
||||
pub const PerformStatus = enum {
|
||||
|
||||
@@ -337,3 +337,26 @@
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="worker_post_before_load" type=module>
|
||||
// Per spec, messages posted before the worker has finished loading must
|
||||
// be buffered and delivered once onmessage is registered. Without the
|
||||
// pending-message queue this hangs: postMessage fires immediately after
|
||||
// new Worker, while the worker script's HTTP fetch is still in flight,
|
||||
// so by the time the worker dispatches the message there is no
|
||||
// onmessage listener yet and the message gets silently dropped.
|
||||
{
|
||||
const state = await testing.async();
|
||||
const worker = new Worker('./echo-worker.js');
|
||||
worker.onmessage = function(event) {
|
||||
state.resolve(event.data);
|
||||
};
|
||||
// No setTimeout — post right now while the script is still loading.
|
||||
worker.postMessage({ greeting: 'before-load' });
|
||||
|
||||
await state.done((response) => {
|
||||
testing.expectEqual('before-load', response.echo.greeting);
|
||||
testing.expectEqual('worker', response.from);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user