16
16
#include < workerd/io/trace.h>
17
17
#include < workerd/jsg/async-context.h>
18
18
#include < workerd/jsg/jsg.h>
19
+ #include < workerd/util/exception.h>
19
20
#include < workerd/util/uncaught-exception-source.h>
20
21
#include < workerd/util/weak-refs.h>
21
22
@@ -1257,23 +1258,42 @@ kj::_::ReducePromises<RemoveIoOwn<T>> IoContext::awaitJs(jsg::Lock& js, jsg::Pro
1257
1258
auto paf = kj::newPromiseAndFulfiller<RemoveIoOwn<T>>();
1258
1259
struct RefcountedFulfiller : public Finalizeable , public kj ::Refcounted {
1259
1260
kj::Own<kj::PromiseFulfiller<RemoveIoOwn<T>>> fulfiller;
1261
+ kj::Own<const AtomicWeakRef<Worker::Isolate>> maybeIsolate;
1260
1262
bool isDone = false ;
1261
1263
1262
- RefcountedFulfiller (kj::Own<kj::PromiseFulfiller<RemoveIoOwn<T>>> fulfiller)
1263
- : fulfiller(kj::mv(fulfiller)) {}
1264
+ RefcountedFulfiller (kj::Own<const AtomicWeakRef<Worker::Isolate>> maybeIsolate,
1265
+ kj::Own<kj::PromiseFulfiller<RemoveIoOwn<T>>> fulfiller)
1266
+ : fulfiller(kj::mv(fulfiller)),
1267
+ maybeIsolate (kj::mv(maybeIsolate)) {}
1264
1268
1265
1269
~RefcountedFulfiller () noexcept (false ) {
1266
1270
if (!isDone) {
1271
+ reject ();
1272
+ }
1273
+ }
1274
+
1275
+ private:
1276
+ void reject () {
1277
+ // We use a weak isolate reference here in case the isolate gets dropped before this code
1278
+ // is executed. In that case we default to `false` as we cannot access the original isolate.
1279
+ auto hasExcessivelyExceededHeapLimit = maybeIsolate->tryAddStrongRef ()
1280
+ .map ([](kj::Own<const Worker::Isolate> isolate) {
1281
+ return isolate->getLimitEnforcer ().hasExcessivelyExceededHeapLimit ();
1282
+ }).orDefault (false );
1283
+ if (hasExcessivelyExceededHeapLimit) {
1284
+ auto e = JSG_KJ_EXCEPTION (OVERLOADED, Error, " Worker has exceeded memory limit." );
1285
+ e.setDetail (MEMORY_LIMIT_DETAIL_ID, kj::heapArray<kj::byte>(0 ));
1286
+ fulfiller->reject (kj::mv (e));
1287
+ } else {
1267
1288
// The JavaScript resolver was garbage collected, i.e. JavaScript will never resolve
1268
1289
// this promise.
1269
1290
fulfiller->reject (JSG_KJ_EXCEPTION (FAILED, Error, " Promise will never complete." ));
1270
1291
}
1271
1292
}
1272
1293
1273
- private:
1274
1294
kj::Maybe<kj::StringPtr > finalize () override {
1275
1295
if (!isDone) {
1276
- fulfiller-> reject (JSG_KJ_EXCEPTION (FAILED, Error, " Promise will never complete. " ) );
1296
+ reject ();
1277
1297
isDone = true ;
1278
1298
return " A hanging Promise was canceled. This happens when the worker runtime is waiting "
1279
1299
" for a Promise from JavaScript to resolve, but has detected that the Promise "
@@ -1284,7 +1304,8 @@ kj::_::ReducePromises<RemoveIoOwn<T>> IoContext::awaitJs(jsg::Lock& js, jsg::Pro
1284
1304
}
1285
1305
}
1286
1306
};
1287
- auto fulfiller = kj::refcounted<RefcountedFulfiller>(kj::mv (paf.fulfiller ));
1307
+ auto & isolate = Worker::Isolate::from (js);
1308
+ auto fulfiller = kj::refcounted<RefcountedFulfiller>(isolate.getWeakRef (), kj::mv (paf.fulfiller ));
1288
1309
1289
1310
auto errorHandler = [fulfiller = addObject (kj::addRef (*fulfiller))](
1290
1311
jsg::Lock& js, jsg::Value jsExceptionRef) mutable {
0 commit comments