@react-router/node 7.18.2 → 7.18.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # `@react-router/node`
2
2
 
3
+ ## v7.18.3
4
+
5
+ ### Patch Changes
6
+
7
+ - fix: Prevent client disconnects during streaming from crashing the Node process ([#15437](https://github.com/remix-run/react-router/pull/15437))
8
+ - Updated dependencies:
9
+ - [`react-router@7.18.3`](https://github.com/remix-run/react-router/releases/tag/react-router@7.18.3)
10
+
3
11
  ## v7.18.2
4
12
 
5
13
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/node v7.18.2
2
+ * @react-router/node v7.18.3
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -164,11 +164,11 @@ async function writeReadableStreamToWritable(stream, writable) {
164
164
  }
165
165
  } catch (error) {
166
166
  try {
167
- reader.cancel(error).catch(() => {
167
+ reader.cancel(error instanceof WritableClosedError ? void 0 : error).catch(() => {
168
168
  });
169
169
  } catch {
170
170
  }
171
- writable.destroy(error);
171
+ destroyWritable(writable, error);
172
172
  throw error;
173
173
  } finally {
174
174
  writableError.cleanup();
@@ -178,8 +178,20 @@ async function writeReadableStreamToWritable(stream, writable) {
178
178
  }
179
179
  }
180
180
  }
181
+ var WritableClosedError = class extends Error {
182
+ };
183
+ function destroyWritable(writable, error) {
184
+ if (error instanceof WritableClosedError || writable.destroyed) {
185
+ return;
186
+ }
187
+ writable.once("error", () => {
188
+ });
189
+ writable.destroy(error);
190
+ }
181
191
  function monitorWritableError(writable) {
192
+ let writableStartedDestroyed = writable.destroyed;
182
193
  let settled = false;
194
+ let writableErrorEmitted = false;
183
195
  let writableError;
184
196
  let rejectWritableError;
185
197
  let writableErrorPromise = new Promise((_, reject2) => {
@@ -188,6 +200,9 @@ function monitorWritableError(writable) {
188
200
  writableErrorPromise.catch(() => {
189
201
  });
190
202
  function cleanup() {
203
+ if (!writableStartedDestroyed && writable.destroyed && writable.errored && !writableErrorEmitted) {
204
+ return;
205
+ }
191
206
  writable.off("error", onError);
192
207
  writable.off("close", onClose);
193
208
  }
@@ -201,10 +216,11 @@ function monitorWritableError(writable) {
201
216
  rejectWritableError(error);
202
217
  }
203
218
  function onError(error) {
219
+ writableErrorEmitted = true;
204
220
  reject(error);
205
221
  }
206
222
  function onClose() {
207
- reject(new Error("Writable closed before stream finished"));
223
+ reject(new WritableClosedError("Writable closed before stream finished"));
208
224
  }
209
225
  writable.once("error", onError);
210
226
  writable.once("close", onClose);
@@ -218,7 +234,9 @@ function monitorWritableError(writable) {
218
234
  throw writableError;
219
235
  }
220
236
  if (writable.destroyed || writable.writableEnded) {
221
- throw new Error("Cannot write to a destroyed or ended writable stream");
237
+ throw new WritableClosedError(
238
+ "Cannot write to a destroyed or ended writable stream"
239
+ );
222
240
  }
223
241
  }
224
242
  };
@@ -265,7 +283,7 @@ async function writeAsyncIterableToWritable(iterable, writable) {
265
283
  } catch {
266
284
  }
267
285
  }
268
- writable.destroy(error);
286
+ destroyWritable(writable, error);
269
287
  throw error;
270
288
  } finally {
271
289
  writableError.cleanup();
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/node v7.18.2
2
+ * @react-router/node v7.18.3
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -124,11 +124,11 @@ async function writeReadableStreamToWritable(stream, writable) {
124
124
  }
125
125
  } catch (error) {
126
126
  try {
127
- reader.cancel(error).catch(() => {
127
+ reader.cancel(error instanceof WritableClosedError ? void 0 : error).catch(() => {
128
128
  });
129
129
  } catch {
130
130
  }
131
- writable.destroy(error);
131
+ destroyWritable(writable, error);
132
132
  throw error;
133
133
  } finally {
134
134
  writableError.cleanup();
@@ -138,8 +138,20 @@ async function writeReadableStreamToWritable(stream, writable) {
138
138
  }
139
139
  }
140
140
  }
141
+ var WritableClosedError = class extends Error {
142
+ };
143
+ function destroyWritable(writable, error) {
144
+ if (error instanceof WritableClosedError || writable.destroyed) {
145
+ return;
146
+ }
147
+ writable.once("error", () => {
148
+ });
149
+ writable.destroy(error);
150
+ }
141
151
  function monitorWritableError(writable) {
152
+ let writableStartedDestroyed = writable.destroyed;
142
153
  let settled = false;
154
+ let writableErrorEmitted = false;
143
155
  let writableError;
144
156
  let rejectWritableError;
145
157
  let writableErrorPromise = new Promise((_, reject2) => {
@@ -148,6 +160,9 @@ function monitorWritableError(writable) {
148
160
  writableErrorPromise.catch(() => {
149
161
  });
150
162
  function cleanup() {
163
+ if (!writableStartedDestroyed && writable.destroyed && writable.errored && !writableErrorEmitted) {
164
+ return;
165
+ }
151
166
  writable.off("error", onError);
152
167
  writable.off("close", onClose);
153
168
  }
@@ -161,10 +176,11 @@ function monitorWritableError(writable) {
161
176
  rejectWritableError(error);
162
177
  }
163
178
  function onError(error) {
179
+ writableErrorEmitted = true;
164
180
  reject(error);
165
181
  }
166
182
  function onClose() {
167
- reject(new Error("Writable closed before stream finished"));
183
+ reject(new WritableClosedError("Writable closed before stream finished"));
168
184
  }
169
185
  writable.once("error", onError);
170
186
  writable.once("close", onClose);
@@ -178,7 +194,9 @@ function monitorWritableError(writable) {
178
194
  throw writableError;
179
195
  }
180
196
  if (writable.destroyed || writable.writableEnded) {
181
- throw new Error("Cannot write to a destroyed or ended writable stream");
197
+ throw new WritableClosedError(
198
+ "Cannot write to a destroyed or ended writable stream"
199
+ );
182
200
  }
183
201
  }
184
202
  };
@@ -225,7 +243,7 @@ async function writeAsyncIterableToWritable(iterable, writable) {
225
243
  } catch {
226
244
  }
227
245
  }
228
- writable.destroy(error);
246
+ destroyWritable(writable, error);
229
247
  throw error;
230
248
  } finally {
231
249
  writableError.cleanup();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-router/node",
3
- "version": "7.18.2",
3
+ "version": "7.18.3",
4
4
  "description": "Node.js platform abstractions for React Router",
5
5
  "bugs": {
6
6
  "url": "https://github.com/remix-run/react-router/issues"
@@ -53,11 +53,11 @@
53
53
  "tsup": "^8.3.0",
54
54
  "typescript": "^5.4.5",
55
55
  "wireit": "0.14.9",
56
- "react-router": "7.18.2"
56
+ "react-router": "7.18.3"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "typescript": "^5.1.0 || ^6.0.0",
60
- "react-router": "7.18.2"
60
+ "react-router": "7.18.3"
61
61
  },
62
62
  "peerDependenciesMeta": {
63
63
  "typescript": {