svelte-adapter-uws 0.4.12 → 0.4.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/files/handler.js CHANGED
@@ -12,7 +12,7 @@ import { manifest, prerendered, base } from 'MANIFEST';
12
12
  import { env } from 'ENV';
13
13
  import * as wsModule from 'WS_HANDLER';
14
14
  import { parseCookies, createCookies } from './cookies.js';
15
- import { mimeLookup, parse_as_bytes, parse_origin } from './utils.js';
15
+ import { mimeLookup, parse_as_bytes, parse_origin, writeChunkWithBackpressure } from './utils.js';
16
16
 
17
17
  /* global ENV_PREFIX */
18
18
  /* global PRECOMPRESS */
@@ -1209,11 +1209,11 @@ async function writeResponse(res, response, state, acceptEncoding) {
1209
1209
  return;
1210
1210
  }
1211
1211
 
1212
- // Multi-chunk streaming response - write headers + first two chunks in one cork.
1213
- // cork() batches these writes into a single syscall, so backpressure from
1214
- // individual res.write() calls inside cork is not actionable - the data is
1215
- // buffered and flushed together when cork returns. The backpressure loop
1216
- // below handles all subsequent chunks.
1212
+ // Multi-chunk streaming response. Headers + first two chunks share one
1213
+ // cork so they flush as a single syscall. Subsequent chunks are each
1214
+ // written inside their own cork via writeChunkWithBackpressure, which
1215
+ // also captures the drain signal from res.write() without tripping the
1216
+ // uWS "writes must be made from within a corked callback" warning.
1217
1217
  if (state.aborted) return;
1218
1218
  streaming = true;
1219
1219
  res.cork(() => {
@@ -1222,17 +1222,13 @@ async function writeResponse(res, response, state, acceptEncoding) {
1222
1222
  res.write(second.value);
1223
1223
  });
1224
1224
 
1225
- // Stream remaining chunks with backpressure (30s timeout per drain)
1226
1225
  for (;;) {
1227
1226
  const { done, value } = await reader.read();
1228
1227
  if (done || state.aborted) break;
1229
1228
 
1230
- const ok = res.write(value);
1231
- if (!ok) {
1232
- const drained = await new Promise((resolve) => {
1233
- const timer = setTimeout(() => resolve(false), 30000);
1234
- res.onWritable(() => { clearTimeout(timer); resolve(true); return true; });
1235
- });
1229
+ const result = writeChunkWithBackpressure(res, value);
1230
+ if (result !== true) {
1231
+ const drained = await result;
1236
1232
  if (!drained) { streamTimedOut = true; break; }
1237
1233
  if (state.aborted) break;
1238
1234
  }
@@ -1243,7 +1239,7 @@ async function writeResponse(res, response, state, acceptEncoding) {
1243
1239
  // Backpressure drained past the 30s deadline. Abruptly close the
1244
1240
  // connection rather than sending a clean EOF on a partial body,
1245
1241
  // which would look like a successful but truncated response.
1246
- res.close();
1242
+ res.cork(() => res.close());
1247
1243
  } else {
1248
1244
  res.cork(() => res.end());
1249
1245
  }
package/files/utils.js CHANGED
@@ -111,6 +111,40 @@ export function parse_as_bytes(value) {
111
111
  return Number(multiplier !== 1 ? normalized.slice(0, -1) : normalized) * multiplier;
112
112
  }
113
113
 
114
+ /**
115
+ * Write a chunk to a uWS HttpResponse inside a cork and, if backpressure
116
+ * builds, return a Promise that resolves when the socket drains or the
117
+ * timeout elapses. Returns `true` synchronously when no drain is needed.
118
+ *
119
+ * All uWS response mutations (write + onWritable registration) happen
120
+ * inside the cork callback, which uWS invokes synchronously, so the
121
+ * boolean return value of `res.write()` is captured correctly.
122
+ *
123
+ * @param {{ cork: (fn: () => void) => void, write: (value: any) => boolean, onWritable: (fn: () => boolean) => void }} res
124
+ * @param {any} value
125
+ * @param {number} [timeoutMs]
126
+ * @returns {true | Promise<boolean>} true if the write succeeded without drain; otherwise a promise that resolves true on drain or false on timeout.
127
+ */
128
+ export function writeChunkWithBackpressure(res, value, timeoutMs = 30000) {
129
+ let ok = false;
130
+ /** @type {Promise<boolean> | null} */
131
+ let drainPromise = null;
132
+ res.cork(() => {
133
+ ok = res.write(value);
134
+ if (!ok) {
135
+ drainPromise = new Promise((resolve) => {
136
+ const timer = setTimeout(() => resolve(false), timeoutMs);
137
+ res.onWritable(() => {
138
+ clearTimeout(timer);
139
+ resolve(true);
140
+ return true;
141
+ });
142
+ });
143
+ }
144
+ });
145
+ return ok ? true : /** @type {Promise<boolean>} */ (drainPromise);
146
+ }
147
+
114
148
  /**
115
149
  * @param {string | undefined} value
116
150
  * @returns {string | undefined}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-adapter-uws",
3
- "version": "0.4.12",
3
+ "version": "0.4.13",
4
4
  "description": "SvelteKit adapter for uWebSockets.js - high-performance C++ HTTP server with built-in WebSocket support",
5
5
  "author": "Kevin Radziszewski",
6
6
  "license": "MIT",