Version 2.17.0-5.0.dev
Merge commit 'e767dca0a69ae25121f83e21e736c66d1b4ef1f4' into 'dev'
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 1f29e90..583e055 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -395,6 +395,10 @@
if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
// Next, look up caller's closure on the stack and walk backwards
// through the yields.
+ //
+ // Due the async/async* closures having optional parameters, the
+ // caller-frame's pushed arguments includes the closure and should never be
+ // modified (even in the event of deopts).
ObjectPtr* last_caller_obj =
reinterpret_cast<ObjectPtr*>(frame->GetCallerSp());
closure = FindClosureInFrame(last_caller_obj, function);
@@ -432,6 +436,12 @@
Object& receiver =
Object::Handle(*(reinterpret_cast<ObjectPtr*>(frame->GetCallerSp()) +
kNumArgsFutureListenerHandleValue));
+ if (receiver.ptr() == Symbols::OptimizedOut().ptr()) {
+ // In the very rare case that _FutureListener.handleValue has deoptimized
+ // it may override the receiver slot in the caller frame with "<optimized
+ // out>" due to the `this` no longer being needed.
+ return Closure::null();
+ }
return caller_closure_finder->GetCallerInFutureListener(receiver);
}
@@ -579,6 +589,9 @@
function.parent_function() != Function::null()) {
if (async_function.ptr() == function.parent_function()) {
if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+ // Due the async/async* closures having optional parameters, the
+ // caller-frame's pushed arguments includes the closure and should
+ // never be modified (even in the event of deopts).
ObjectPtr* last_caller_obj =
reinterpret_cast<ObjectPtr*>(frame->GetCallerSp());
closure = FindClosureInFrame(last_caller_obj, function);
diff --git a/tools/VERSION b/tools/VERSION
index df09db5..0b7b793 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 4
+PRERELEASE 5
PRERELEASE_PATCH 0
\ No newline at end of file