@sproutboat/runtime 0.13.1 → 0.13.2
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 +6 -0
- package/package.json +1 -1
- package/src/native-fetch-prelude.js +27 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @sproutboat/runtime
|
|
2
2
|
|
|
3
|
+
## 0.13.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- dc6539c: Log uncaught handler exceptions to stderr before answering 500, as `Uncaught (in fetch) Error: ...` (and `scheduled` / `alarm` for those triggers). A thrown or rejected handler used to produce a bare 500 with nothing logged, which hid baronunread/sproutboat#168 entirely.
|
|
8
|
+
|
|
3
9
|
## 0.13.1
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1993,27 +1993,43 @@ async function __sbFetchWithDrain(res, tasks) {
|
|
|
1993
1993
|
let r;
|
|
1994
1994
|
try {
|
|
1995
1995
|
r = res && __sbIsFn(res.then) ? await res : res;
|
|
1996
|
-
} catch {
|
|
1996
|
+
} catch (error) {
|
|
1997
1997
|
// #179 — a rejected handler promise must not take the process down with it.
|
|
1998
|
-
r = __sbErrorResponse();
|
|
1998
|
+
r = __sbErrorResponse(error);
|
|
1999
1999
|
}
|
|
2000
2000
|
await __sbDrainWaitUntil(tasks);
|
|
2001
2001
|
return r;
|
|
2002
2002
|
}
|
|
2003
2003
|
|
|
2004
2004
|
// #179 — turn an uncaught handler exception into a 500 instead of letting it
|
|
2005
|
-
// propagate past __sbEntry and crash the whole server.
|
|
2006
|
-
|
|
2005
|
+
// propagate past __sbEntry and crash the whole server. Logged first, the way a
|
|
2006
|
+
// Worker logs "Uncaught Error: ...": a swallowed exception left a 500 with
|
|
2007
|
+
// nothing on stderr, which hid #168 entirely.
|
|
2008
|
+
function __sbErrorResponse(error) {
|
|
2009
|
+
__sbLogUncaught("fetch", error);
|
|
2007
2010
|
return new Response("Internal Server Error", { status: 500 });
|
|
2008
2011
|
}
|
|
2009
2012
|
|
|
2013
|
+
function __sbLogUncaught(where, error) {
|
|
2014
|
+
try {
|
|
2015
|
+
let text = "";
|
|
2016
|
+
if (error && error.stack) text = String(error.stack);
|
|
2017
|
+
else if (error && error.message != null) text = (error.name || "Error") + ": " + error.message;
|
|
2018
|
+
else text = String(error);
|
|
2019
|
+
console.error("Uncaught (in " + where + ") " + text);
|
|
2020
|
+
} catch {
|
|
2021
|
+
/* logging must never turn a handled error into a crash */
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2010
2025
|
// Shared by alarm and scheduled: both reply with an empty 204 once their
|
|
2011
2026
|
// handler (and anything it queued via `waitUntil`) has settled.
|
|
2012
2027
|
async function __sb204WithDrain(res, tasks) {
|
|
2013
2028
|
try {
|
|
2014
2029
|
if (res && __sbIsFn(res.then)) await res;
|
|
2015
|
-
} catch {
|
|
2030
|
+
} catch (error) {
|
|
2016
2031
|
// #179 — same rule as fetch: a rejected scheduled/alarm promise must not crash the process.
|
|
2032
|
+
__sbLogUncaught("scheduled/alarm", error);
|
|
2017
2033
|
}
|
|
2018
2034
|
await __sbDrainWaitUntil(tasks);
|
|
2019
2035
|
return new Response("", { status: 204 });
|
|
@@ -2082,10 +2098,10 @@ globalThis.__sbEntry = function (handlers, request) {
|
|
|
2082
2098
|
__res = globalThis.__sbCompat >= "2026-09-28"
|
|
2083
2099
|
? handlers.fetch(request, globalThis.env, ctx)
|
|
2084
2100
|
: handlers.fetch(request, ctx);
|
|
2085
|
-
} catch {
|
|
2101
|
+
} catch (error) {
|
|
2086
2102
|
// #179 — a synchronous throw anywhere in the handler must not take the
|
|
2087
2103
|
// whole process (and every other in-flight request) down with it.
|
|
2088
|
-
return __sbErrorResponse();
|
|
2104
|
+
return __sbErrorResponse(error);
|
|
2089
2105
|
}
|
|
2090
2106
|
// Same promise-identity rule as above applies to `__sbFetchWithDrain`'s
|
|
2091
2107
|
// own return, which is why it's tail-called rather than chained on here.
|
|
@@ -2112,8 +2128,9 @@ globalThis.__sbEntry = function (handlers, request) {
|
|
|
2112
2128
|
__sres = globalThis.__sbCompat >= "2026-09-28"
|
|
2113
2129
|
? handlers.scheduled(event, globalThis.env, ctx)
|
|
2114
2130
|
: handlers.scheduled(event, ctx);
|
|
2115
|
-
} catch {
|
|
2131
|
+
} catch (error) {
|
|
2116
2132
|
// #179 — same rule as fetch: don't let a throw here crash the process.
|
|
2133
|
+
__sbLogUncaught("scheduled", error);
|
|
2117
2134
|
return new Response("", { status: 204 });
|
|
2118
2135
|
}
|
|
2119
2136
|
if (__sbTasks.length || (__sres && __sbIsFn(__sres.then))) return __sb204WithDrain(__sres, __sbTasks);
|
|
@@ -2146,8 +2163,9 @@ globalThis.__sbEntry = function (handlers, request) {
|
|
|
2146
2163
|
let __ares;
|
|
2147
2164
|
try {
|
|
2148
2165
|
__ares = inst.alarm();
|
|
2149
|
-
} catch {
|
|
2166
|
+
} catch (error) {
|
|
2150
2167
|
// #179 — same rule as fetch: don't let a throw here crash the process.
|
|
2168
|
+
__sbLogUncaught("alarm", error);
|
|
2151
2169
|
return new Response("", { status: 204 });
|
|
2152
2170
|
}
|
|
2153
2171
|
// Was fire-and-forget before: an async `alarm()` and any `state.waitUntil()`
|