@react-router/node 8.3.0 → 8.4.0
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 +18 -0
- package/dist/index.js +31 -14
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# `@react-router/node`
|
|
2
2
|
|
|
3
|
+
## v8.4.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix a memory leak in `writeReadableStreamToWritable` and `writeAsyncIterableToWritable` that retained memory for the lifetime of a long-running stream ([#15500](https://github.com/remix-run/react-router/pull/15500))
|
|
8
|
+
- Preserve error handling when a producer closes the destination while reading the next chunk
|
|
9
|
+
- Updated dependencies:
|
|
10
|
+
- [`react-router@8.4.0`](https://github.com/remix-run/react-router/releases/tag/react-router@8.4.0)
|
|
11
|
+
|
|
12
|
+
## v8.3.1
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Bump `@remix-run/node-fetch-server` dependency ([#15447](https://github.com/remix-run/react-router/pull/15447))
|
|
17
|
+
- fix: Prevent client disconnects during streaming from crashing the Node process ([#15324](https://github.com/remix-run/react-router/pull/15324))
|
|
18
|
+
- Updated dependencies:
|
|
19
|
+
- [`react-router@8.3.1`](https://github.com/remix-run/react-router/releases/tag/react-router@8.3.1)
|
|
20
|
+
|
|
3
21
|
## v8.3.0
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/node v8.
|
|
2
|
+
* @react-router/node v8.4.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -123,9 +123,9 @@ async function writeReadableStreamToWritable(stream, writable) {
|
|
|
123
123
|
}
|
|
124
124
|
} catch (error) {
|
|
125
125
|
try {
|
|
126
|
-
reader.cancel(error).catch(() => {});
|
|
126
|
+
reader.cancel(error instanceof WritableClosedError ? void 0 : error).catch(() => {});
|
|
127
127
|
} catch {}
|
|
128
|
-
writable
|
|
128
|
+
destroyWritable(writable, error);
|
|
129
129
|
throw error;
|
|
130
130
|
} finally {
|
|
131
131
|
writableError.cleanup();
|
|
@@ -134,15 +134,20 @@ async function writeReadableStreamToWritable(stream, writable) {
|
|
|
134
134
|
} catch {}
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
|
+
var WritableClosedError = class extends Error {};
|
|
138
|
+
function destroyWritable(writable, error) {
|
|
139
|
+
if (error instanceof WritableClosedError || writable.destroyed) return;
|
|
140
|
+
writable.once("error", () => {});
|
|
141
|
+
writable.destroy(error);
|
|
142
|
+
}
|
|
137
143
|
function monitorWritableError(writable) {
|
|
144
|
+
let writableStartedDestroyed = writable.destroyed;
|
|
138
145
|
let settled = false;
|
|
146
|
+
let writableErrorEmitted = false;
|
|
139
147
|
let writableError;
|
|
140
|
-
let
|
|
141
|
-
let writableErrorPromise = new Promise((_, reject) => {
|
|
142
|
-
rejectWritableError = reject;
|
|
143
|
-
});
|
|
144
|
-
writableErrorPromise.catch(() => {});
|
|
148
|
+
let pendingRejections = /* @__PURE__ */ new Set();
|
|
145
149
|
function cleanup() {
|
|
150
|
+
if (!writableStartedDestroyed && writable.destroyed && writable.errored && !writableErrorEmitted) return;
|
|
146
151
|
writable.off("error", onError);
|
|
147
152
|
writable.off("close", onClose);
|
|
148
153
|
}
|
|
@@ -151,24 +156,36 @@ function monitorWritableError(writable) {
|
|
|
151
156
|
settled = true;
|
|
152
157
|
writableError = error;
|
|
153
158
|
cleanup();
|
|
154
|
-
|
|
159
|
+
let rejections = [...pendingRejections];
|
|
160
|
+
pendingRejections.clear();
|
|
161
|
+
for (let rejectPending of rejections) rejectPending(error);
|
|
155
162
|
}
|
|
156
163
|
function onError(error) {
|
|
164
|
+
writableErrorEmitted = true;
|
|
157
165
|
reject(error);
|
|
158
166
|
}
|
|
159
167
|
function onClose() {
|
|
160
|
-
reject(
|
|
168
|
+
reject(new WritableClosedError("Writable closed before stream finished"));
|
|
161
169
|
}
|
|
162
170
|
writable.once("error", onError);
|
|
163
171
|
writable.once("close", onClose);
|
|
164
172
|
return {
|
|
165
173
|
cleanup,
|
|
166
174
|
race(promise) {
|
|
167
|
-
return Promise.race([promise,
|
|
175
|
+
if (writableError) return Promise.race([promise, Promise.reject(writableError)]);
|
|
176
|
+
let rejectPending;
|
|
177
|
+
let pendingPromise = new Promise((_, reject) => {
|
|
178
|
+
rejectPending = reject;
|
|
179
|
+
});
|
|
180
|
+
pendingPromise.catch(() => {});
|
|
181
|
+
pendingRejections.add(rejectPending);
|
|
182
|
+
return Promise.race([promise, pendingPromise]).finally(() => {
|
|
183
|
+
pendingRejections.delete(rejectPending);
|
|
184
|
+
});
|
|
168
185
|
},
|
|
169
186
|
throwIfClosed() {
|
|
170
187
|
if (writableError) throw writableError;
|
|
171
|
-
if (writable.destroyed || writable.writableEnded) throw new
|
|
188
|
+
if (writable.destroyed || writable.writableEnded) throw new WritableClosedError("Cannot write to a destroyed or ended writable stream");
|
|
172
189
|
}
|
|
173
190
|
};
|
|
174
191
|
}
|
|
@@ -206,7 +223,7 @@ async function writeAsyncIterableToWritable(iterable, writable) {
|
|
|
206
223
|
if (!completed) try {
|
|
207
224
|
Promise.resolve(iterator.return?.()).catch(() => {});
|
|
208
225
|
} catch {}
|
|
209
|
-
writable
|
|
226
|
+
destroyWritable(writable, error);
|
|
210
227
|
throw error;
|
|
211
228
|
} finally {
|
|
212
229
|
writableError.cleanup();
|
|
@@ -265,7 +282,7 @@ var StreamPump = class {
|
|
|
265
282
|
let available = (this.controller.desiredSize || 0) - bytes.byteLength;
|
|
266
283
|
this.controller.enqueue(bytes);
|
|
267
284
|
if (available <= 0) this.pause();
|
|
268
|
-
} catch
|
|
285
|
+
} catch {
|
|
269
286
|
this.controller.error(/* @__PURE__ */ new Error("Could not create Buffer, chunk must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object"));
|
|
270
287
|
this.cancel();
|
|
271
288
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-router/node",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.4.0",
|
|
5
5
|
"description": "Node.js platform abstractions for React Router",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/remix-run/react-router/issues"
|
|
@@ -38,18 +38,18 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@remix-run/node-fetch-server": "^0.
|
|
41
|
+
"@remix-run/node-fetch-server": "^0.14.1"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^22.19.19",
|
|
45
45
|
"tsdown": "^0.22.0",
|
|
46
46
|
"typescript": "^6.0.3",
|
|
47
47
|
"wireit": "0.14.12",
|
|
48
|
-
"react-router": "8.
|
|
48
|
+
"react-router": "8.4.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"typescript": "^5.1.0 || ^6.0.0 || ^7.0.0",
|
|
52
|
-
"react-router": "8.
|
|
52
|
+
"react-router": "8.4.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"typescript": {
|